「Git」分支管理


分支基本操作

指令 解释
git branch 查看本地分支
git branch -a 可以查看本地和远程仓库的分支
git branch -vv 将所有的本地分支列出来并且包含更多的信息,如每一个分支正在跟踪哪个远程分支与本地分支是否是领先、落后或是都有。一般需要先git fetch --all更新远程数据
git branch <name> 创建分支
git checkout <name>
git switch<name>
切换到已有的分支
git checkout -b <name>
git switch -c <name>
创建并切换分支
git merge <name> 将某个分支合并到当前的分支
git branch -d <name> 删除分支
git branch -D <name> 强制删除分支(如果删除一个没有被合并的分支,只能用该指令而不能用-d)
git checkout -b <本地分支名> origin/<远程分支名> 在本地创建一个和远程仓库origin中某分支相关联的分支(名字最好是一样的)
git branch --set-upstream <本地分支名> origin/<远程分支名> 将本地已经存在的某分支和远程库的某分支建立关联

分支合并——merge

我们可以通过git merge <name>进行两个分支的合并,其效果是将名为<name>的分支里的内容合并到当前所在的分支上。当我们进行分支合并时,有的时候需要解决冲突,举下面三个例子——

  • Position 1
    如果我们在master分支上新建了一个dev分支,并在dev上修改了一个文件并提交,这样dev分支就比master分支提前一步,如下图所示

    此时我们切换到master分支,并使用指令git merge dev,此时git就直接将master的指针移动到了dev上,如图

    这种模式被称作 快进模式Fast-forward),仅仅通过移动指针即可完成,不需要我们进行冲突合并。

  • Position 2
    接上例,如果禁用Faster-forward模式会怎样? 答:Git会自动在master上生成一个新的提交,该提交是两者合并后的结果,然后master指向该次提交,如下图所示

    如何禁用Faster-forward模式呢?我们只需要在当前分支切换到master后,使用。因为这种合并方式需要在master上创建一个新的提交,所以需要输入提交描述信息。

  • Position 3
    我们再换一个例子。假设master分支上有一个空文件readme.txt(已经提交到版本库), 然后我们在master分支上新建一个dev分支,这样两个分支都有空文件readme.txt

    • 之后我们切换到在dev分支上,在readme.txt的第一行添加了一句 “dev modify it!”, 保存之后commit到本地仓库。
    • 然后我们在切换到master分支上,此时readme.txt还是一个空文件。我们在readme.txt的第一行添加了一句 “master modify it!”, 保存之后也commit到本地仓库

    此时,masterdev两个分支是真的分道扬镳了!如下图所示——

    这种情况下,如果在master分支中使用指令git merge dev,则可能产生冲突。因为我们在两个分支上同时对readme.txt加了一行,但是内容不同,Git并不知道该保存哪个。此时使用merge命令后,Git会提示我们 “Automatic merge failed; fix conflicts and then commit the result.” 也就是说自动给合并失败了,需要我们手动结局冲突后再次提交。

    我们打开readme.txt,会发现内容变成了

    <<<<<<< HEAD
    master modify it!
    =======
    dev modify it!
    >>>>>>> dev

    此时我们手动修改之后再commit即可。

此外,如果在手动合并时出现了失误,我们可以通过git merge --abort回到合并前的状态。


分支变基——rebase

命令格式

变基命令的一般格式为——

git rebase <basebranch> <topicbranch>

其中basebranch是作为新基底的分支,topicbranch是待变基的分支。当然,如果你想让当前所在的分支作为topicbranch,可以直接使用git rebase <basebranch>

用法解释

git rebase的官方解释是——"当执行rebase操作时,git会从两个分支的共同祖先开始提取待变基分支上的修改,然后将待变基分支指向基分支的最新提交,最后将刚才提取的修改应用到基分支的最新提交的后面。"我们用下面的例子来分析

此时master指向的是C4dev指向的是C6,它们的公共祖先是C2。此时我们在dev分支上调用命令git rebase master,Git就会比较C5C6C2之间的区别,然后将C5C6C2的修改应用在C4上(即C4作为新的基底),形成新的提交C5'C6',最后再将原先的C5C6删掉。其效果相当于将dev上的两个提交记录(C5C6)拿下来,安到master的最新提交(C4)上。

操作结果如下图所示——

可以发现,变基实际上就是更改历史,使得提交历史成为一条直线而没有分叉。这样做的好处是能够保持提交历史的整洁性,但是缺点也很明显——丢弃了一些提交记录,如果你的同伴是基于这些记录进行开发,那就会使事情变得很麻烦。

因此,如果正在和同伴协作开发,应该尽量避免使用rebase。如果真出现了"有人推送了经过变基的提交,并丢弃了你的本地开发所基于的一些提交",我们可以通过两种方法解决(具体可参见《Pro Git》的相关章节)
- 第一种:先使用get fetch --all获取同伴使用变基后的提交记录,然后使用get rebase origin/master(也就是用变基解决变基)。
- 第二种:在下拉时使用git pull --rebase,而不是使用git pull


分支拣选——cherry-pick

Git 中的拣选类似于对特定的某次提交的变基。 它会提取该提交的补丁,之后尝试将其重新应用到当前分支上。 这种方式在你只想引入某个分支中的某个提交,或者某个分支中只有一个提交,而你不想运行变基时很有用。假设你的项目提交历史如下图所示——

此时如果想要将提交e43a6拉去到master分支,我们可以先切换到master分支,然后使用命令git cherry-pick e43a6。这样一来,master分支会新增一个提交,结果如下——


文章作者: Hyggge
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Hyggge !
  目录