git 简明使用手册

git 使用简明手册

 
 
git 是由Linus Torvalds领衔开发的一款开源、分布式版本管理系统,显然,git最初是为了帮助管理Linux内核开发而开发的版本控制系统。
版本控制系统本身并不要求一个中央服务器(远端仓库)来存储所有数据,虽然svn是这样做的。
Git允许克隆仓库,克隆的仓库跟被克隆的仓库的数据和功能完全一样,中央服务器的概念只是使用上的一种习惯;
每个仓库都可以和其它仓库交换文件,从而实现仓库数据的同步。

 

代码在workspace、本地仓库、远端仓库之间的数据同步流程图如下:

git

 

 

从上面的流程图可以看出,本地git仓库(Repository)是由三棵“树”组成:

1、工作目录(working space),它持有实际文件;

2、暂存区(Index/Stage),它像个缓存区域,临时保存你的改动;

3、当前版本(HEAD),HEAD^ 指上一版本,HEAD^^ 指上上一个版本,HEAD~100往上100个版本。

 

 

开发人员在working space中对文件做的修改,需要先add到index,然后再提交到HEAD(即Repository)。
PS:如果在add之后,commint之前又修改了文件,这些修改不会自动保存到index,需要再次执行add命令;
 

 可见,working space与本地仓库Repository之间的代码流动,跟SVN的workspace和服务器中央仓库之间的流动类似,通过checkout、add、commit命令控制。

与SVN不一样的是,git是分布式的,不存在一个托管所有代码的“中央服务器”。

或者从某种意义上来说,git有很多“中央服务器”,这些“中央服务器”可以是本地仓库,也可以是远端仓库,仓库之间也可以进行代码同步。

 

一、git 常见的应用场景

代码提交(Merge Request)流程

  • git checkout -b ${branch_name},创建并切换分支
  • git checkout ${branch_name},只切换分支
  • git add ${file_name},将工作目录中修改过的文件添加到暂存区(working space -> Index)
  • git commit -m "${msg}",将暂存区的文件提交到本地仓库(Index -> HEAD)
  • git remote add origin ${server},关联到远程仓库(这是先有本地仓库,后有远程仓库的情况,反之就用git clone命令将远程仓库复制到本地)
  • git push origin ${branch_name},将本地某个分支的修改推送到远端服务器(远程仓库已存在)
 

撤销修改(未提交到版本库)

  • git checkout -- ${file_name},丢弃在working space的修改;
  • git reset HEAD ${file_name},撤销已经保存到index(但没有commit)的修改,修改会回滚到working space中;
  • git reset --hard origin/${branch_name},用远程仓库的文件覆盖本地的修改(包括working space和Index);
 

版本回退(已提交到版本库)

  • git reset --hard HEAD^,回退到上一个版本;
  • git reset --hard ${commit_id},滚动到指定版本;

 

更新本地仓库

  • git pull,将远程仓库的修改拉取到本地仓库;
  • git merge ${branch_name},将指定分支合并到当前分支;
  • git fetch origin,

 

 

二、git 分支管理

git 会把每次提交串成一条时间线,这条时间线就是一个分支,例如下面的master分支:

每次提交,master就向前一步,master指向最近一次提交,而HEAD指向master,所以HEAD就指向了当前分支的提交点。

 

 

当创建一个分支dev时,Git新建一个指针dev,指向与master相同的提交点,再把HEAD指向dev,就表示当前分支在dev上

 

如上图,可见Git创建一个分支很快,因为除了增加一个dev指针,再修改HEAD的指向,working space的文件都没有任何变化!

不过,从现在开始,对working space的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变

 

假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并

所以Git合并分支也很快!就改改指针,working space内容也不变!

上面这种merge方式是快进模式(Fast-forward ),直接把master指向dev的当前提交,所以合并速度非常快。但这种模式下,删除分支后,会丢掉分支信息。当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。

合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

 

 


Git鼓励大量使用分支:

  • 查看分支:git branch,-a 列出所有分支, -r 远程分支;
  • 创建分支:git branch ${branch_name}
  • 切换分支:git checkout ${branch_name}
  • 创建并切换分支:git checkout -b ${branch_name}
  • 合并某分支到当前分支:git merge ${branch_name},--no-ff 选项可以关闭Fast-forward合并模式;
  • 删除分支:git branch -d ${branch_name},如果分支还未合并到主分支会报错;
  • 强制删除:git branch -D ${branch_name},丢弃一个没有被合并过的分支,删除后无法恢复;

 

 

冲突

考虑一种更复杂的情况,master分支和dev分支各自都有新的提交,变成了这样:

 

此时git merge命令可能会产生冲突(如果修改了通过一个文件),

此时可以用git status查看冲突文件,并手动修改冲突文件然后保存,再利用git add和git commit命令提交。

上面这种merge方式不能用Fast-forward模式,而是像这样:

 

 

 

stash

有时候我们需要在当前开发分支(dev)中,停下来去处理bug,而当前dev分支没有完成,又不能提交到master,这个时候可以使用stash功能。

  • git stash, 保存现场(包括working space和Index)到stash;
  • git stash pop,恢复现场,并把stash内容也删除;
  • git stash list,查看stash内容;
  • git stash show -p stash@{0},查看指定stash内容;
  • git stash apply,只恢复现场,不删除stash内容;
  • git stash drop stash@{0},删除指定stash内容,会返回一个id;
  • git stash store -m "msg" ${drop返回的id},修改存在的stash message,先drop,拿到drop返回的id 执行该命令即可。

 

 

 

 

 

三、Git命令

创建新仓库(init)

创建新文件夹,打开,然后执行 

git init

以创建新的 git 仓库。

 

克隆仓库(clone)

执行如下命令以创建一个本地仓库的克隆版本:

git clone /path/to/repository 

如果是远端服务器上的仓库,你的命令会是这个样子:

git clone username@host:/path/to/repository

 该命令会在本地主机生成一个目录,与远程主机的版本库同名。如果要指定不同的目录名,可以将目录名作为git clone命令的第二个参数:

git clone <版本库的网址> <本地目录名>

另外,git clone支持多种协议,除了HTTP(s)以外,还支持SSH、Git、本地文件协议等,下面是一些例子:

git clone http[s]://example.com/path/to/repo.git/
git clone ssh://example.com/path/to/repo.git/
git clone git://example.com/path/to/repo.git/
git clone /opt/git/project.git 
git clone file:///opt/git/project.git
git clone ftp[s]://example.com/path/to/repo.git/
git clone rsync://example.com/path/to/repo.git/

 

远程仓库(remote)

列出所有的远程主机名:

git remote 

加上选项-v可以查看远程主机的地址

 

对远程主机的操作:

git remote show <主机名>    
git remote add <主机名> <网址>    
git remote rm <主机名>
git remote rename <原主机名> <新主机名>

 

 

查看(diff/status/log)

查看版本修改的历史日志

git log --pretty=oneline

 

git的版本号与SVN的纯数字不一样,它是一个SHA1计算出来的一个非常大的数字,用十六进制表示。

 

查看working space的具体修改

git diff 
git diff filename

 

查看working space的修改状态

git status

 

 

 

推送改动(push)

你的改动现在已经在本地仓库的 HEAD 中了。执行如下命令以将这些改动提交到远端仓库:

git push <远程主机名> <本地分支名>:<远程分支名>

如果省略远程分支名,则表示将本地分支推送与之存在"追踪关系"的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。


 

分支(checkout)

分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master 是“默认的”分支。在其他分支上进行开发,完成后再将它们合并到主分支上。

 

创建一个叫做“feature_x”的分支,并切换过去:

git checkout -b feature_x

切换回主分支:

git checkout master

 

除非你将分支推送到远端仓库,不然该分支就是不为他人所见的

git push origin <branch>

 

在某些场合,Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。

比如,在git clone的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master分支自动"追踪"origin/master分支。

Git也允许手动建立追踪关系:

git branch --set-upstream master origin/next

 上面命令指定master分支追踪origin/next分支。

 

获取分支(fetch)

fetch命令可以将远端主机的更新取回本地:

git fetch <远程主机名> <分支名>

若省略<分支名>,则更新远程主机的全部分支。

所取回的更新,在本地主机上要用"远程主机名/分支名"的形式读取,比如origin主机的next分支,就要用origin/next读取。

 

 

取回远程主机的更新以后,可以在它的基础上,使用git checkout命令创建一个新的分支

git checkout -b newBrach origin/next

 

此外,也可以使用git merge命令或者git rebase命令,在本地分支上合并远程分支

git merge origin/next
或者
git rebase origin/next

 

更新与合并(pull)

取回远程主机某个分支的更新,再与本地的指定分支合并:

git pull <远程主机名> <远程分支名>:<本地分支名>

如果本地分支名是当前分支,本地分支名可以省略不写;

如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名。

 

 

git pull origin

 

上面命令表示,本地的当前分支自动与对应的origin主机"追踪分支"(remote-tracking branch)进行合并。

如果当前分支只有一个追踪分支,连远程主机名都可以省略:

git pull

上面命令表示,当前分支自动与唯一一个追踪分支进行合并。

 

例如,取回远程主机origin的next分支,与本地的master分支合并,可以执行:

git pull origin next:master

 

这等同于先做git fetch,再做git merge:

git fetch origin next
git merge origin/next

 

 

在这两种情况下,git 都会尝试去自动合并改动。遗憾的是,这可能并非每次都成功,并可能出现冲突(conflicts)。 这时候就需要你修改这些文件来手动合并这些冲突(conflicts)。改完之后,你需要执行如下命令以将它们标记为合并成功:

git add <filename>

在合并改动之前,你可以使用如下命令预览差异:

git diff <source_branch> <target_branch>

 

标签(tag)

TAG就是指向某个commit的指针。你可以执行如下命令创建一个叫做 1.0.0 的标签:

git tag 1.0.0  1b2e1d63ff

1b2e1d63ff 是你想要标记的提交 ID 的前 10 位字符。可以使用下列命令获取提交 ID:

git log

你也可以使用少一点的提交 ID 前几位,只要它的指向具有唯一性。

如果不写commit ID,则默认取最近的提交(即默认HEAD)。

tag的作用主要是比commit id更方便记忆 。

 

git tag -d ${tag_name}, 删除本地标签
git push origin :refs/tags/${tag_name},删除远程仓库的标签
git push origin ${tag_name},将指定标签push到远程仓库
git push origin --tags,将所有标签push到远程仓库

 


 

替换本地改动

假如你操作失误(当然,这最好永远不要发生),你可以使用如下命令替换掉本地改动:

git checkout -- <filename>

此命令会使用 HEAD 中的最新内容替换掉你的工作目录中的文件。已添加到暂存区的改动以及新文件都不会受到影响。

假如你想丢弃你在本地的所有改动与提交,可以到服务器上获取最新的版本历史,并将你本地主分支指向它:

git fetch origin
git reset --hard origin/master

 

 

 

posted @ 2014-09-28 11:07  如果的事  阅读(870)  评论(0编辑  收藏  举报