如果我使用标准的主分支-功能分支开发流程,将一个功能分支合并到主分支和将其 cherry-pick 到主分支之间有什么区别?
示例分支:
m1 -- m2 master
\-- f1 -- f2 feature
我认为两者输出相同,即
m1 -- m2 -- -- -- m3 master
\-- f1 -- f2 feature
如果我使用标准的主分支-功能分支开发流程,将一个功能分支合并到主分支和将其 cherry-pick 到主分支之间有什么区别?
示例分支:
m1 -- m2 master
\-- f1 -- f2 feature
我认为两者输出相同,即
m1 -- m2 -- -- -- m3 master
\-- f1 -- f2 feature
在merge --squash
和cherry-pick
之间有两个重要的区别:
也就是说,如果你有像上面描述的情况,并且你(在master
分支上)执行git cherry-pick feature
,结果分支会看起来像这样:
m1 -- m2 -- f2’ master
\-- f1 -- f2 feature
这意味着来自 f1
的更改不会出现在主分支上(如果 f2
依赖于它们,那么可能无法使用 Cherry-pick)。
merge --squash
不会立即提交,而是创建所有更改的概要,并使其准备好提交。 这本质上是您完整分支更改的补丁,与 git diff m1..feature
显示的相同。
在我的机器上,快速测试产生了这个输出:
$ test git:(master) git merge --squash testbranch
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
这里重要的部分是“不更新HEAD”,这是“git术语”,意为“我没有提交我所做的内容”。实际上,第二句话更容易理解……
如果您喜欢逐步开发(通过在每次成功测试运行之后进行提交,例如使用一个提交记录来记录所有导致解决方案的小步骤)。则此功能很方便。在这种情况下,您的历史记录可能会混乱,有成百上千个一行提交记录。因此,最好定期进行合并压缩提交(例如,在您开发完一部分功能之后)。
挑选让你能够将另一个提交引入的更改应用到当前分支。
与压缩合并(跟随提交)相比,合并执行相同的操作(关于生成的工作目录和索引,而不是历史记录)。
以下是一个示例(git的某些输出未显示)。
设置
$ git init
$ echo sahred file > shared-file.txt
$ git add .
$ git commit -m 'added shared-file.txt in master branch'
$ git checkout -b dev
$ touch dev.txt
$ git add .
$ git commit -m 'added dev.txt in dev branch'
$ echo shared file > shared-file.txt
$ git add .
$ git commit -m 'fixed typo in shared-file.txt in dev branch'
$ git checkout master
dev
的分支,其中包含一个额外的文件(dev.txt
),并且修复了shared-file.txt
中的拼写错误。我们切换回master
分支来比较挑选和合并。
挑选
$ git cherry-pick dev
$ git log --oneline --graph
* 8019b05 (HEAD -> master) fixed typo in shared-file.txt in dev branch
* 7dbd3aa added shared-file.txt in master branch
$ ls
shared-file.txt
$ cat shared-file.txt
shared file
dev
分支中的最后一个提交引入的更改(修复了shared-file.txt
中的拼写错误),但是附加文件dev.txt
并没有被带过来,因为它不是在dev
分支中的最后一个提交中创建的。$ git reset HEAD~1 --hard # undo cherry-pick
$ git merge dev --squash
$ git commit -m 'merged dev'
$ git log --oneline --graph
* 01dd755 (HEAD -> master) merged dev
* 7dbd3aa added shared-file.txt in master branch
$ ls
dev.txt shared-file.txt
$ cat shared-file.txt
shared file
dev.txt
也被保留下来。这是因为使用压缩合并(随后提交)与常规合并两个提交在生成的工作目录和索引方面是相同的(但历史记录当然不同)。