我有一个(大)提交树,其中包含几个我想要重新绑定到另一个提交的合并提交.执行正常的rebase会导致git要求我解决合并冲突.我不想审查每个合并,因为这将是很多工作.在找到--preserve-merges选项后,这里有一个很好的解释,我认为我找到了完成这项任务的完美工具.但是,我似乎无法让它正常工作.我创建了一个演示问题的玩具示例.
从空文件夹开始,我们首先创建一个带有合并的分支和另一个我们将在其上进行rebase的分支.
A---B--
\ \
---C---D
\
---E
Run Code Online (Sandbox Code Playgroud)
其中主指乙,分支指d和再见分支指È.
git init
echo Hello > Hello.txt
git add Hello.txt
git commit -m "Create Hello.txt (commit A)"
git tag start
echo World! >> Hello.txt
git commit -am "Change to Hello World (commit B)"
git checkout start
git checkout -b branch
echo Dave >> Hello.txt
git commit -am "Change to Hello Dave (commit C)"
git merge master
echo Hello World, Dave! > Hello.txt
git add Hello.txt
git commit -m "Merge branch master into branch (commit D)"
git checkout start
git checkout -b goodbye-branch
echo Goodbye > Goodbye.txt
git add Goodbye.txt
git commit -m "Add Goodbye.txt (commit E)"
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很顺利.发生了合并冲突,但我们已经解决了.现在我们尝试将分支重新绑定到E以最终得到以下提交树:
A---E----B'
\ \
C'---D'
git checkout branch
git rebase -p goodbye-branch
Run Code Online (Sandbox Code Playgroud)
这样结束时出现以下错误:
Auto-merging Hello.txt
CONFLICT (content): Merge conflict in Hello.txt
Automatic merge failed; fix conflicts and then commit the result.
Error redoing merge f567809e2cc91244cc7fdac210e1771dc75e4d86
Run Code Online (Sandbox Code Playgroud)
该文件包含以下内容:
Hello
<<<<<<< HEAD
Dave
=======
World!
>>>>>>> 0437403c97f33f229e41ec9584ce891a50052e48
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?我希望git能够使用提交D来解决它在重新定位时遇到的合并冲突.
我正在使用Git 1.9.4.msysgit.1,这是目前最新的版本.
jub*_*0bs 27
该--preserve-merges标志只是告诉git-rebase尝试重新创建合并提交而不是忽略它们.它不给git rebase记住如何合并冲突得到解决的能力,即它不记录以供将来使用冲突的决议.你想要用的是什么rerere.
在您的玩具示例中,rebase期间产生的冲突与您在前一次合并期间解决的冲突完全相同.如果在合并rerere 之前已激活,则不必在rebase期间再次解决该冲突.
如果您预计要合并,然后重新绑定分支,则应激活,rerere以便将来只需要解决一次给定的合并冲突,而不是多次.
让我们分解你的玩具示例.
git init
echo Hello > Hello.txt
git add Hello.txt
git commit -m "Create Hello.txt (commit A)"
git tag start
echo World! >> Hello.txt
git commit -am "Change to Hello World (commit B)"
git checkout start
git checkout -b branch
echo Dave >> Hello.txt
git commit -am "Change to Hello Dave (commit C)"
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.在您的第一个git merge命令之前,您的仓库看起来像这样:

在提交A中,Hello.text包含
Hello
Run Code Online (Sandbox Code Playgroud)
在提交B中,Hello.text包含
Hello
World!
Run Code Online (Sandbox Code Playgroud)
并在commit C中Hello.text包含
Hello
Dave
Run Code Online (Sandbox Code Playgroud)
现在,当您尝试合并master到branch运行
git merge master
Run Code Online (Sandbox Code Playgroud)
Git报告合并冲突,因为它无法自行确定Hello.txt合并后的内容是否应该是
Hello
World!
Dave
Run Code Online (Sandbox Code Playgroud)
要么
Hello
Dave
World!
Run Code Online (Sandbox Code Playgroud)
或者是其他东西...
您可以通过覆盖Hello.txtwith 的内容Hello World, Dave!,暂存更改以及完成合并提交来解决该冲突.
echo "Hello World, Dave!" > Hello.txt
git add Hello.txt
git commit -m "Merge branch master into branch (commit D)"
Run Code Online (Sandbox Code Playgroud)
你的回购现在看起来像这样:

然后你跑
git checkout start
git checkout -b goodbye-branch
echo Goodbye > Goodbye.txt
git add Goodbye.txt
git commit -m "Add Goodbye.txt (commit E)"
Run Code Online (Sandbox Code Playgroud)
在那个阶段,您的仓库看起来如下:

现在你跑
git checkout branch
git rebase -p goodbye-branch
Run Code Online (Sandbox Code Playgroud)
但遇到冲突.在解释为什么会出现这种冲突之前,让我们看看如果该git-rebase操作成功(即无冲突),您的回购将会是什么样子:

现在让我们看看为什么你Hello.txt在第一次合并时遇到了同样的冲突; Goodbye.txt这里没有任何问题.实际上可以通过一系列更基本的操作(checkouts和cherry-picks)来分解rebase ; 更多内容见http://think-like-a-git.net/sections/rebase-from-the-ground-up.html.长话短说......在您的git rebase操作过程中,您的仓库将如下所示:

情况与第一次合并之前的情况非常相似:在提交B'中,Hello.text包含
Hello
World!
Run Code Online (Sandbox Code Playgroud)
在提交C'中,Hello.text包含
Hello
Dave
Run Code Online (Sandbox Code Playgroud)
然后Git尝试创建合并B'和C',但出现合并冲突的原因与您遇到的第一次合并冲突的原因完全相同:Git无法确定该Dave行应该在行之前还是之后World!.因此,rebase操作会停止运行,Git会要求您在完成rebase之前解决该合并冲突.
rerereGit rerere是你的朋友,在这里.
该名称代表"重复记录的分辨率",顾名思义,它允许您让Git记住您是如何解决大块冲突的,以便下次看到相同的冲突时,Git可以自动为您解决.
[...]如果你想要一个你合并的分支并修复了一堆冲突,然后决定改变它 - 你可能不必再做同样的冲突了.
如果rerere已启用,
git config --global rerere.enabled true
Run Code Online (Sandbox Code Playgroud)
在合并之前,Git会记录您在创建提交D时如何解决合并冲突,并且在后续rebase期间遇到相同的冲突时会应用相同的解决方案.冲突仍然会中断rebase操作,但它会自动解决.你所要做的就是git rebase --continue.
但是,它似乎rerere在合并之前尚未激活,这意味着Git必须没有记录您第一次如何解决冲突.在此阶段,您可以立即激活rerere并再次手动解决所有相同的冲突,也可以使用rerere-train.sh脚本(另请参阅此博客文章)使用现有历史记录预先设置rerere缓存.
| 归档时间: |
|
| 查看次数: |
2788 次 |
| 最近记录: |