Git的使用方法(转)

作者:暗夜星辰 发布于:2013-12-20 14:50 Friday 分类:LINUX && VPS

Git 是用于Linux 内核开发的版本控制工具。与常用的CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持,使源代码的发布和交流极其方便。
Ubuntu上可以在“system  ->   系统管理 -> 新立得软件包管理器”中搜索到git-core, 这个下载下来即可很方便的开始使用git了。

下面从用户角度分两部分讲述,首先是单个用户独立使用git,其次是多个用户一起使用git进行团队开发。

一:单个用户

先在自己的 /home/chenchi/ 目录下开始操作
$ mkdir gittest

$ cd gittest

$ git init
 然后会自动输出类似的语句 :
Initialized empty Git repository in /home/chenchi/testgit/.git/
这时候我们输入下面的命令
$ ls  -a
可以看到当前目录下创建了一个隐藏的 .git 目录,它就是所谓的Git 仓库,不过现在仓库还是空的。另外当前目录也不再是普通的文档目录了,今后我们将其称为工作树。有兴趣的话,可以先到.git 目录下看看都有哪些文件。

 一个叫 HEAD 的文件,我们现在来查看一下它的内容:

$ cat .git/HEAD

现在 HEAD 的内容应该是这样:

ref: refs/heads/master

我们可以看到,HEAD 文件中的内容其实只是包含了一个索引信息,并且,这个索引将总是指向你的项目中的当前开发分支。

一个叫 objects 的子目录,它包含了你的项目中的所有对象,我们不必直接地了解到这些对象内容,我们应该关心是存放在这些对象中的项目的数据。

一个叫 refs 的子目录,它用来保存指向对象的索引。

具体地说,子目录 refs 包含着两个子目录叫 heads 和 tags,就像他们的名字所表达的意味一样:他们存放了不同的开发分支的头的索引, 或者是你用来标定版本的标签的索引。

请注意:master 是默认的分支,这也是为什么 .git/HEAD 创建的时候就指向 master 的原因,尽管目前它其实并不存在。 git 将假设你会在 master 上开始并展开你以后的工作,除非你自己创建你自己的分支。

另外,这只是一个约定俗成的习惯而已,实际上你可以将你的工作分支叫任何名字,而不必在版本库中一定要有一个叫 master 的分支,尽管很多 git 工具都认为 master 分支是存在的。

现在已经创建好了一个 git 版本库,但是它是空的,还不能做任何事情,下一步就是怎么向版本库植入数据了。

为了简明起见,我们创建两个文件作为练习:
$ echo "Hello world" > hello
$ echo "Silly example" > example

这样在当前的testgit目录下就生成了两个文件hello和example,如果我们想将它们加入到库中,该怎么做呢?
首先利用 git add 命令将这两个文件加入到版本库文件索引(一个临时的存储区域,Git 称该区域为索引,如果不理解,先跳过去)当中:
$ git add hello example

现在让我们看看版本库的状态:
$ git status

# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached ..." to unstage)
#
#       new file: example
#       new file: hello
#
我们能看到 git 的状态提示。提示信息告诉我们版本库中加入了两个新的文件,并且 git 提示我们提交这些文件,我们可以通过 git-commit 命令来提交,这里我们有两种输入方式,

(1)带参数m

$ git commit -m "Initial commit of gittest reposistory"

//引号中的内容就是类似于SVN中每次提交代码前,都要填写的message信息,以便于以后自己或者别人能明白你这次更改的原因,及相关改动的信息。

(2)不带参数m

$ git commit

//系统会自动调用一个叫GNU nano的编辑器,来让你输入与上面类似的信息,在编辑器的下面会出现^G  ^X ^O   ^J等等,^表示ctrl键,所以他们分别是“ctrl键+G”(获取帮助),“ctrl键+X”(Exit 退出),“ctrl键+O”(WriteOut 写保存),“ctrl键+J”(Justify),具体就不详述了。
Created initial commit 7ffe128: Initial commit of gittest reposistory
 2 files changed, 2 insertions(+), 0 deletions(-)
 create mode 100644 example
 create mode 100644 hello

 来看看自己的劳动成果吧:

$ git  log

commit 7ffe1285bda6febfa8d24f8d366ad97c97f3b550
Author: chenchi << span="">chen.chi@kortide.com.cn>
Date:   Tue Feb 24 17:54:46 2009 +0800

    Initial commit of gittest reposistory
这里我们已经知道如何创建版本库,并向库中添加数据。

再往下走:

$ vim hello

添加如下语句:
today is Tuesday, 20090224, rain.
Are you happy?

利用git diff 查看改了什么:

$ git diff            //注意:该命令只比较已经在index索引中存在的文件,也即如果是一个新加的文件。git diff是不会产生比较的。
diff --git a/hello b/hello
index 802992c..e042b07 100644
--- a/hello
+++ b/hello
@@ -1 +1,4 @@
 Hello world
+
+today is Tuesday, 20090224, rain.
+Are you happy?

现在让我们看看版本库的状态:
$ git status

# On branch master          //表示master分支
#   (use "git add ..." to update what will be committed)
#
#       modified:   hello
#
no changes added to commit (use "git add" and/or "git commit -a")它表示hello文件已经被更改了,但没有更新(update)。

$ git add hello

$ git diff                                //此时已经没有不同的内容了

$ git status              //再看看版本库状态,有什么区别呢?

# On branch master                 //表示master分支
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#       modified:   hello
#
它表示hello文件已经被更改了,但没有提交(committed)到本地的仓库中

$ git commit -m "1---add date to hello file"

这里我们其实已经完成了又一次的更改和提交了。

 

二:多个用户,团队开发

实际开发中,我们通常是直接用别人的仓库来进行进一步的开发,那么下面的流程就是必须要看的了:

因为是团队合作,所以每个人在使用git时,要先进行类似的配置。

$ git config --global user.name "chenchi"$ git config --global user.email "chen.chi@kortide.com.cn"

这样的配置文件也可以在/home/chenchi/.gitconfig中看到。

回到自己的 /home/chenchi/ 目录下

$ mkdir project
$ cd  project

首先从服务器上克隆(clone出完整的工作树到本地):

$ git clonechenchi@192.168.2.171:/home/chenchi/git1   (内网用户)

$ git clone  ssh://chenchi@210.22.155.236:9092/home/chenchi/git1   (外网用户)
Initialized empty Git repository in /home/chenchi/project/git1/.git/chenchi@192.168.2.171's password:    输入服务器上chenchi用户的密码(123456),然后输出下面的内容
remote: Counting objects: 94, done.
remote: Compressing objects: 100% (67/67), done.
remote: Total 94 (delta 12), reused 0 (delta 0)
Receiving objects: 100% (94/94), 7.91 KiB, done.
Resolving deltas: 100% (12/12), done.

注意:

     1:git clone 命令是将别的仓库克隆(clone)过来,后面是别人仓库的源地址,你可以直接用上面的地址试试。这时如果一切顺利,系统会自动在你的当前目录下建立一个git1的目录;如果你想弄一个linux的源代码来玩玩,可以试试这个:

     $ git-clone  git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git  linux-2.6


    2:因为git clone在默认时用的是ssh协议,所以用git clone前应该确保我们当前机器机器上已经安装了openssh,详见wiki中: 开发环境 ------> Openssh服务 。

    这样在当前目录中就生产了一个git1的工作树,它的内容和服务器中是一样的。你可以在自己的机器上进行各种更改了,具体用法和前面单机时类似(add  -> commit   ->OK  )。只是当你想将自己的工作放到服务器中时(也就是SVN中的提交代码),建议按如下步骤:

$ git  pull              

 //先更新本地代码,使其是服务器中最新的代码,防止提交时有冲突,如果没有,继续下一步;如果有冲突,则先在编辑器中修改掉冲突部分,再继续下面的步骤

$ git  push  //将本地的更改最后push到服务器上,使服务器上也同步保留了自己的更改

这里一次代码更改并最后提交就完成了。

这个时候在服务器端可以用 git log 来看看是否有更新,同时可以通过在服务器端输入 git checkout  将Git仓库中更新的内容导到当前工作目录中,显现出来。

当服务器上有新的代码(其他人git  push  上去的),而某个开发者在本地忘记了git pull,直接git push 时,会出现类似下面的错误:

zhenguo@zhenguo-desktop:~/chenchi/git1/drv-pxa310$ git pushzhenguo@210.22.155.236's password:
 To ssh://210.22.155.236:9092/home/chenchi/git1
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to 'ssh://210.22.155.236:9092/home/chenchi/git1'

这时需要git pull 更新本地代码,系统会在这个过程中自动的进行merger操作,如果本地更改和服务器上最新代码没有冲突,则merger操作自动完成,如果有冲突,则出现类似下面的输出:

zhenguo@zhenguo-desktop:~/chenchi/git1/drv-pxa310$ git pullzhenguo@210.22.155.236's password:
 remote: Counting objects: 15, done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 12 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (12/12), done.
From ssh://210.22.155.236:9092/home/chenchi/git1
   a3803c8..9ceb8ee  master     -> origin/master
Auto-merged drv-pxa310/t3
CONFLICT (content): Merge conflict in drv-pxa310/t3
Automatic merge failed; fix conflicts and then commit the result.

这时需要我们自己手动更改文件,再提交到本地仓库,最后 git push 到服务器上去。

如果在push过程中有类似下面的错误:

zhenguo@zhenguo-desktop:~/chenchi/git1/drv-pxa310$ git pushzhenguo@210.22.155.236's password:
 Counting objects: 14, done.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 755 bytes, done.
Total 8 (delta 4), reused 0 (delta 0)
error: unable to create temporary sha1 filename ./objects/ca: File exists

fatal: failed to write object
error: unpack failed: unpacker exited with error code
To ssh://210.22.155.236:9092/home/chenchi/git1
 ! [remote rejected] master -> master (n/a (unpacker error))
error: failed to push some refs to 'ssh://210.22.155.236:9092/home/chenchi/git1'

 

三:库的逆转与恢复  --  git-reset   --  git-checkout编辑本段回目录


 库的逆转与恢复除了用来进行一些废弃的研发代码的重置外,还有一个重要的作用。比如我们从远程clone了一个代码库,在本地开发后,准备提交回远程。但是本地代码库在开发时,有功能性的commit,也有出于备份目的的commit等等。总之,commit的日志中有大量无用log,我们并不想把这些log在提交回远程时也提交到库中。 因此,就要用到git-reset。
Git-reset的概念比较复杂。它的命令形式:git-reset [--mixed | --soft | --hard] []
命令的选项:


--mixed  这个是默认的选项。 如

$ git   reset   --mixed    dev1^              / /dev1^ 其实就是某个具体的commit ID,也就是那一串数字,如 a3803c862eb73b3a7a61b356e3fb5c7e95a17bfd

它的作用仅是重置分支状态到dev1^,  但是却不改变任何工作文件的内容。即,从dev1^到dev1的所有文件变化都保留了,但是dev1^到dev1之间的所有commit日志都被清除了,而且,发生变化的文件内容也没有通过git-add标识,如果您要重新commit,还需要对变化的文件做一次git-add。简单点说就是:将前面几次log信息清除,而将相应的更改一次性进行 add --> commit。 这样,add --> commit后,就会得到了一份非常干净的提交记录。

$ git   reset   --mixed    7fde43204             //相当于做了git-reset –mixed,后,又对变化的文件做了git-add。如果用了该选项, 就可以直接commit了。

$ git   reset   --hard    7fde43204              //这个命令就会导致所有信息的回退, 包括文件内容。 一般只有在重置废弃代码时,才用它。 执行后,文件内容也无法恢复回来了。慎用。

 

当我们改了大量的文件以后,既没有 git add 也没有git commit,这时我们想将其中部分文件的更改撤销掉,即想做SVN中的revert类似操作,这时可以:

$ git   checkout    HEAD   --   filename1   filename2  filename3   dir1/filename4  dir1/filename4

 

四 .Git pull、 push 操作无需输密码的方法编辑本段回目录

在本地使用git与服务器进行pull、push操作时,每次都要输入密码,比较麻烦,我们可以用ssh密钥来进行验证。这样git使用过程中ssh就会自动登录而无需输入密码。方法如下:
首先用自己账号登录到server上,输入ssh-keygen -t rsa

chenchi@Ubuntu-8:~$ ssh-keygen -t rsaGenerating public/private rsa key pair.
Enter file in which to save the key (/home/chenchi/.ssh/id_rsa):
 Enter passphrase (empty for no passphrase):
 Enter same passphrase again:
 Your identification has been saved in /home/chenchi/.ssh/id_rsa.
Your public key has been saved in /home/chenchi/.ssh/id_rsa.pub.
The key fingerprint is:
79:8a:78:8f:c6:12:12:3c:fd:40:84:7b:e3:fc:60:dfchenchi@Ubuntu-8
The key's randomart image is:
.........
输入ssh-keygen -t rsa后,出现各个提示,不用管,一直按回车。这样密钥对就生成完了。其中公共密钥保存在 ~/.ssh/id_rsa.pub ( ~ 表示自己账号的home目录,像我的就是/home/chenchi目录);
私有密钥保存在 ~/.ssh/id_rsa 文件中。
chenchi@Ubuntu-8:~$ cd .ssh/chenchi@Ubuntu-8:~/.ssh$ lsconfig  id_rsa  id_rsa.pub  known_hosts
chenchi@Ubuntu-8:~/.ssh$ cat id_rsa.pub  >> authorized_keyschenchi@Ubuntu-8:~/.ssh$<span style="color: rgb(73, 73, 73);font-siz

标签: linux mod

发表评论:

©2012-2014 woodbunny.com 木头♥兔子的小屋 sitemap