2016-07-14 125 views
2

要重现这种情况,我现在可以执行以下操作。git rebase vs git rebase <upstream>

git checkout -b parent --track 
touch check.yml 
cat > check.yml <<EOL 
1 
2 
3 
EOL 
git add --all 
git commit -m "parent branch" 
git checkout -b child --track 
vim check.yml # Change 1 to 11 
git add --all 
git commit -m child 
git checkout parent 
vim check.yml # change 3 to 31 
git add --all 
git commit --amend 

现在,如果我你运行git rebase parent child-1你会得到一个合并冲突,但如果你git checkout child-1 && git rebase,你不会得到一个冲突。

下面是运行这两个git命令的跟踪。

$:~/webroot/test-repo$ GIT_TRACE=1 git rebase parent child-1 
trace: exec: 'git-rebase' 'parent' 'child-1' 
trace: run_command: 'git-rebase' 'parent' 'child-1' 
trace: built-in: git 'rev-parse' '--parseopt' '--' 'parent' 'child-1' 
trace: built-in: git 'rev-parse' '--git-dir' 
trace: built-in: git 'rev-parse' '--is-bare-repository' 
trace: built-in: git 'rev-parse' '--show-toplevel' 
trace: built-in: git 'config' '--bool' 'rebase.stat' 
trace: built-in: git 'config' '--bool' 'rebase.autostash' 
trace: built-in: git 'config' '--bool' 'rebase.autosquash' 
trace: built-in: git 'rev-parse' '--verify' 'parent^0' 
trace: built-in: git 'rev-parse' '--verify' 'parent^0' 
trace: built-in: git 'show-ref' '--verify' '--quiet' '--' 'refs/heads/child-1' 
trace: built-in: git 'rev-parse' '-q' '--verify' 'refs/heads/child-1' 
trace: built-in: git 'rev-parse' '--verify' 'HEAD' 
trace: built-in: git 'update-index' '-q' '--ignore-submodules' '--refresh' 
trace: built-in: git 'diff-files' '--quiet' '--ignore-submodules' 
trace: built-in: git 'diff-index' '--cached' '--quiet' '--ignore-submodules' 'HEAD' '--' 
trace: built-in: git 'merge-base' 'd29fb1b0ab2eefba0f8ef13fd4e37d61acb9ee6f' '75d8979d743ba575de680fd04d517aa74e813819' 
First, rewinding head to replay your work on top of it... 
trace: built-in: git 'checkout' '-q' 'd29fb1b0ab2eefba0f8ef13fd4e37d61acb9ee6f^0' 
trace: built-in: git 'update-ref' 'ORIG_HEAD' '75d8979d743ba575de680fd04d517aa74e813819' 
trace: built-in: git 'format-patch' '-k' '--stdout' '--full-index' '--ignore-if-in-upstream' '--src-prefix=a/' '--dst-prefix=b/' '--no-renames' '--no-cover-letter' 'd29fb1b0ab2eefba0f8ef13fd4e37d61acb9ee6f..75d8979d743ba575de680fd04d517aa$ 
4e813819' 
trace: exec: 'git-am' '--rebasing' '--resolvemsg= 
When you have resolved this problem, run "git rebase --continue". 
If you prefer to skip this patch, run "git rebase --skip" instead. 
To check out the original branch and stop rebasing, run "git rebase --abort". 
' 
trace: run_command: 'git-am' '--rebasing' '--resolvemsg= 
When you have resolved this problem, run "git rebase --continue". 
If you prefer to skip this patch, run "git rebase --skip" instead. 
To check out the original branch and stop rebasing, run "git rebase --abort". 
' 
trace: built-in: git 'rev-parse' '--parseopt' '--' '--rebasing' '--resolvemsg= 
When you have resolved this problem, run "git rebase --continue". 
If you prefer to skip this patch, run "git rebase --skip" instead. 
To check out the original branch and stop rebasing, run "git rebase --abort". 
' 
trace: built-in: git 'rev-parse' '--git-dir' 
trace: built-in: git 'rev-parse' '--show-prefix' 
trace: built-in: git 'rev-parse' '--show-toplevel' 
trace: built-in: git 'var' 'GIT_COMMITTER_IDENT' 
trace: built-in: git 'rev-parse' '--verify' '-q' 'HEAD' 
trace: built-in: git 'config' '--bool' '--get' 'am.keepcr' 
trace: built-in: git 'mailsplit' '-d4' '-o/home/schuettm/webroot/test-repo/.git/rebase-apply' '-b' '--' 
trace: built-in: git 'update-index' '-q' '--refresh' 
trace: built-in: git 'diff-index' '--cached' '--name-only' 'HEAD' '--' 
trace: built-in: git 'cat-file' '-t' '5290c010a2c88dc29a019cb8f08ece9162a6482c' 
trace: built-in: git 'cat-file' 'commit' '5290c010a2c88dc29a019cb8f08ece9162a6482c' 
trace: built-in: git 'config' 'i18n.commitencoding' 
trace: built-in: git 'show' '-s' '--pretty=raw' '--encoding=UTF-8' '5290c010a2c88dc29a019cb8f08ece9162a6482c' '--' 
trace: built-in: git 'diff-tree' '--root' '--binary' '--full-index' '5290c010a2c88dc29a019cb8f08ece9162a6482c' 
Applying: parent 
trace: built-in: git 'apply' '--build-fake-ancestor' '/home/schuettm/webroot/test-repo/.git/rebase-apply/patch-merge-tmp-index' '/home/schuettm/webroot/test-repo/.git/rebase-apply/patch' 
trace: built-in: git 'write-tree' 
Using index info to reconstruct a base tree... 
trace: built-in: git 'diff-index' '--cached' '--diff-filter=AM' '--name-status' 'HEAD' 
trace: built-in: git 'apply' '--cached' 
trace: built-in: git 'write-tree' 
Falling back to patching base and 3-way merge... 
trace: built-in: git 'merge-recursive' '4b825dc642cb6eb9a060e54bf8d69288fbee4904' '--' 'HEAD' 'bf8853bde213ddd00cb31b3d22906cf746dcc2fd' 
Auto-merging check.yml 
CONFLICT (add/add): Merge conflict in check.yml 
trace: built-in: git 'rerere' 
Failed to merge in the changes. 
Patch failed at 0001 parent 
trace: built-in: git 'config' '--bool' 'advice.amworkdir' 
The copy of the patch that failed is found in: 
    /home/schuettm/webroot/test-repo/.git/rebase-apply/patch 

When you have resolved this problem, run "git rebase --continue". 
If you prefer to skip this patch, run "git rebase --skip" instead. 
To check out the original branch and stop rebasing, run "git rebase --abort". 

trace: built-in: git 'rev-parse' '--verify' '-q' 'HEAD' 

$:~/webroot/test-repo$ GIT_TRACE=1 git rebase                                            
trace: exec: 'git-rebase' 
trace: run_command: 'git-rebase' 
trace: built-in: git 'rev-parse' '--parseopt' '--' 
trace: built-in: git 'rev-parse' '--git-dir' 
trace: built-in: git 'rev-parse' '--is-bare-repository' 
trace: built-in: git 'rev-parse' '--show-toplevel' 
trace: built-in: git 'config' '--bool' 'rebase.stat' 
trace: built-in: git 'config' '--bool' 'rebase.autostash' 
trace: built-in: git 'config' '--bool' 'rebase.autosquash' 
trace: built-in: git 'rev-parse' '--verify' 'refs/heads/parent^0' 
trace: built-in: git 'rev-parse' '--verify' 'refs/heads/parent^0' 
trace: built-in: git 'symbolic-ref' '-q' 'HEAD' 
trace: built-in: git 'rev-parse' '--verify' 'HEAD' 
trace: built-in: git 'merge-base' '--fork-point' 'refs/heads/parent' 'HEAD' 
trace: built-in: git 'rev-parse' '--verify' 'HEAD' 
trace: built-in: git 'update-index' '-q' '--ignore-submodules' '--refresh' 
trace: built-in: git 'diff-files' '--quiet' '--ignore-submodules' 
trace: built-in: git 'diff-index' '--cached' '--quiet' '--ignore-submodules' 'HEAD' '--' 
trace: built-in: git 'merge-base' 'd29fb1b0ab2eefba0f8ef13fd4e37d61acb9ee6f' '75d8979d743ba575de680fd04d517aa74e813819' 
First, rewinding head to replay your work on top of it... 
trace: built-in: git 'checkout' '-q' 'd29fb1b0ab2eefba0f8ef13fd4e37d61acb9ee6f^0' 
trace: built-in: git 'update-ref' 'ORIG_HEAD' '75d8979d743ba575de680fd04d517aa74e813819' 
trace: built-in: git 'format-patch' '-k' '--stdout' '--full-index' '--ignore-if-in-upstream' '--src-prefix=a/' '--dst-prefix=b/' '--no-renames' '--no-cover-letter' '5290c010a2c88dc29a019cb8f08ece9162a6482c..75d8979d743ba575de680fd04d517aa7 
4e813819' 
trace: exec: 'git-am' '--rebasing' '--resolvemsg= 
When you have resolved this problem, run "git rebase --continue". 
If you prefer to skip this patch, run "git rebase --skip" instead. 
To check out the original branch and stop rebasing, run "git rebase --abort". 
' 
trace: run_command: 'git-am' '--rebasing' '--resolvemsg= 
When you have resolved this problem, run "git rebase --continue". 
If you prefer to skip this patch, run "git rebase --skip" instead. 
To check out the original branch and stop rebasing, run "git rebase --abort". 
' 
trace: built-in: git 'rev-parse' '--parseopt' '--' '--rebasing' '--resolvemsg= 
When you have resolved this problem, run "git rebase --continue". 
If you prefer to skip this patch, run "git rebase --skip" instead. 
To check out the original branch and stop rebasing, run "git rebase --abort". 
' 
trace: built-in: git 'rev-parse' '--git-dir' 
trace: built-in: git 'rev-parse' '--show-prefix' 
trace: built-in: git 'rev-parse' '--show-toplevel' 
trace: built-in: git 'var' 'GIT_COMMITTER_IDENT' 
trace: built-in: git 'rev-parse' '--verify' '-q' 'HEAD' 
trace: built-in: git 'config' '--bool' '--get' 'am.keepcr' 
trace: built-in: git 'mailsplit' '-d4' '-o/home/schuettm/webroot/test-repo/.git/rebase-apply' '-b' '--' 
trace: built-in: git 'update-index' '-q' '--refresh' 
trace: built-in: git 'diff-index' '--cached' '--name-only' 'HEAD' '--' 
trace: built-in: git 'cat-file' '-t' '75d8979d743ba575de680fd04d517aa74e813819' 
trace: built-in: git 'cat-file' 'commit' '75d8979d743ba575de680fd04d517aa74e813819' 
trace: built-in: git 'config' 'i18n.commitencoding' 
trace: built-in: git 'show' '-s' '--pretty=raw' '--encoding=UTF-8' '75d8979d743ba575de680fd04d517aa74e813819' '--' 
trace: built-in: git 'diff-tree' '--root' '--binary' '--full-index' '75d8979d743ba575de680fd04d517aa74e813819' 
Applying: child 
trace: built-in: git 'write-tree' 
trace: built-in: git 'rev-parse' '--verify' '-q' 'HEAD' 
trace: built-in: git 'commit-tree' '4db00e2710f88742114576a8a7d5ee6875f433c3' '-p' 'd29fb1b0ab2eefba0f8ef13fd4e37d61acb9ee6f' 
trace: built-in: git 'update-ref' '-m' 'rebase: child' 'HEAD' 'f7d50b6e381e0894904bd122d13c5880f8583916' 
trace: built-in: git 'notes' 'copy' '--for-rewrite=rebase' 
trace: built-in: git 'rev-parse' 'HEAD' 
trace: built-in: git 'update-ref' '-m' 'rebase finished: refs/heads/child-1 onto d29fb1b0ab2eefba0f8ef13fd4e37d61acb9ee6f' 'refs/heads/child-1' 'f7d50b6e381e0894904bd122d13c5880f8583916' '75d8979d743ba575de680fd04d517aa74e813819' 
trace: built-in: git 'symbolic-ref' '-m' 'rebase finished: returning to refs/heads/child-1' 'HEAD' 'refs/heads/child-1' 
trace: built-in: git 'gc' '--auto' 

如果你盯着它一会儿,它看起来像这个问题是git rebase使用git 'merge-base' '--fork-point' 'refs/heads/parent' 'HEAD'确定合并基础,从该名男子页还使用了引用日志助阵这很可能是为什么它会提出修改意见,而不会因为冲突而停下来。

什么神奇的论据被传递到git rebase下,让它具有这种功能?

的git的重订该名男子页说branch.<name>.remotebranch.<name>.merge但是被使用时,我在看他们与混帐配置后,我得到一个无效的上游错误替换这些值,所以我猜他们以某种方式在内部扩大之前使用,我不明白。

回答

1

你是对的,它是--fork-point魔法。这实际上是documented

如果<上游>未指定,则在上游分支配置。 <名称> .remote和分支。 <名称>。将使用合并选项(详情请参阅git-config(1)),并假定--fork-point选项。如果您当前没有在任何分支上,或者当前分支没有配置上游,那么rebase会中止。

您可以手动将--fork-point添加到您自己的rebase命令中以获得相同的效果。

--fork-point的行为并不是世界上最容易描述的,并且将重定位文档链接到the git merge-base documentation。它有一个很好的图,但仍然留下很多描述方面的要求。

由于--fork-point依赖于reflogs,只有当您的上游分支reflog保留关键信息时它才会起作用。通常情况下,这是90天(可到达提交到期)或30天(无法到达提交到期)。这个does not make it any easier to describe. :-)提到它的意图可能会有所帮助:它意味着帮助从上游rebase恢复,并且确实如此。

+0

虽然我已经很好地阅读了手册页,但我仍然觉得真的很愚蠢。然而,我使用的git版本没有记录这一点。感谢更好的解释! – mschuett

+0

有一段时间,fork-point在'git pull'中是魔法,根本没有任何rebase。然后它被转移到'git rebase',但没有记录。你必须有一个Git的过渡版本... – torek

0

我会离开这个开放的人谁知道更多关于这个,然后我。但在阅读了被称为重新绑定的git-rebase.sh脚本后,我发现由于某种原因,当您拨打git rebase而没有参数时,--fork-point会被奇迹般地添加。所以git rebasegit rebase --fork-point parent-branch相同。