ILD

git branching
作者:Herbert Yuan 邮箱:yuanjp@hust.edu.cn
发布时间:2018-5-12 站点:Inside Linux Development

有些人将Git的branching模型称为它的杀手锏。上一节Git internals,我们弄懂了Git的内部原理,但是覆盖的不全。不篇继续学习一些内部原理,同时也全面学习相关的命令。


Index

index也叫做暂存区。用来构建commit要提交的内容。当完成一次提交后,index和那次提交保持一致,然后你可以通过git add等命令来往index中添加、删除文件。然后使用git commit来提交新的index。


Branches in a Nutshell

branch只是一个指向commit的可移动的指针。默认的branch名字叫做master。当你开始提交,master都指向你最后一次commit,并且每次commit,它都自动向前移动。


创建一个新的branch:

1
$ git branch testing

新的branch在创建的时候,和当前branch一致,指向同一个commit。之后你可以切换到新的branch,commit一些提交,此时新branch就和旧的branch分道扬镳了。


git有一个特殊的指针叫做HEAD,它表示当前的branch。


切换分支:

1
$ git checkout testing

该命令执行后,HEAD指向testing分支。


Basic Branching and Merging

将另外一个分支合并到当前分支:

1
$ git merge hotfix

Git创建一个快照,该快照是两个分支的合并,并且创建一个merge commit,这个commit有两个parent。


合并时,Git决定两个分支的共同祖先。合并后,可以删除hotfix分支。


冲突的解决办法:

当两个分支修改了同一行内容,那么将产生冲突,如下将testing merge到master,a文件master修改为c,testing修改为b,产生冲突:

1
2
3
4
5
6
7
8
9
10
$ git merge testing
Auto-merging a
CONFLICT (content): Merge conflict in a
Automatic merge failed; fix conflicts and then commit the result.
cat a
<<<<<<< HEAD
c
=======
b
>>>>>>> testing

编辑后,提交:

1
2
$ vim a
$ git commit -a -m 'fix conflict'

上述commit的父为之前的两个分支的最后一次commit。


也可以使用mergetool来解决冲突。


Remote Branches

Remote references是那些位于远程仓库的引用,包括branches,tags等。使用git ls-remote显示remote references,或者git remote show显示远程分支。


Remote-tracking branches是不可移动的本地引用,表示远程分支在本地的状态。只有当你推送或者拉取数据时,Remote-tracking branch才移动。


Remote-tracking branches的形式为<remote>/<branch>


git fetch <remote>

用来从服务器同步新的更新,它移动origin/master分支。‘


git push <remote> <branch>

推送本地分支到服务器


Tracking branches

从remote-tracking branch checkout一个本地branch,将自动创建一个tracking branch。它track的branch叫做upstream branch。tracking branches是这些和remote branch有直接关系的branch。


当你处于tracking branch,并且执行git pull,git知道从那个服务器的哪个分支提取数据合并。


当你克隆一个仓库时,git自动创建一个track origin/master的分支master,可以手动创建tracking branches

1
2
$ git checkout -b <branch> <remote>/<branch>
$ git checkout --track origin/serverfix


当执行

1
$ git checkout serverfix

如果本地不存在serverfix,但是远端存在,此时会自动创建一个tracking branch。


upstream shorthand

@{upstream} @{u} 表示当前分支的upstream branch

因此,如果当前分支是master,git merge @{u}等价于git merge origin/master


使用git branch -vv可以显示branch对应的upstream branch


Pulling

git fetch命令,将从服务器fetch down所有的你还没有的改动,但是并不会更新你的本地工作目录,需要你手动合并。

git pull命令等于git fetch命令,立即跟着一个git merge命令。


Deleting Remote Branches

使用下述命令:

1
$ git push origin --delete serverfix


这样只是将branch的指针移除,并不会删除数据,直到执行garbage collection相关的命令。


Rebasing

Git有两种主要的方式,将一个branch的改变集成到另一个branch:merge和rebase。


merge是两个分支最后一次commit的合并。


下面是rebase的例子:

1
2
$ git checkout experiment
$ git rebase master

它寻找共同的祖宗,然后把experiment的每个改动生成一个patch,apply到master分支,然后experiment指向apply后的地方。master分支不变。


此时,可以切换到master分支,执行fast-forward merge

1
2
$ git checkout master
$ git merge experiment


结果和merge是一样的,但是rebase有一个更清晰的历史记录。


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.