2016-07-14 167 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相同。