【问题标题】:git rebase vs git rebase <upstream>git rebase vs git rebase <上游>
【发布时间】:2016-07-14 18:57:39
【问题描述】:

要重现我所处的情况,您可以执行以下操作。

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 &amp;&amp; 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' 来确定 man page 中的合并基础,该基础也使用 reflog 来提供帮助,这可能是它选择修改并且不会因冲突而停止。

什么神奇的参数被传递给 git rebase 以使其具有此功能?

git rebase 的手册页说使用了 branch.&lt;name&gt;.remotebranch.&lt;name&gt;.merge 但是当我用 git config 查找它们后替换这些值时,我得到一个无效的上游错误,所以我猜它们在某些地方被扩展了使用前的内部方式,我不明白。

【问题讨论】:

    标签: git


    【解决方案1】:

    你是对的,这是--fork-point 的魔法。这其实是documented

    如果 未指定,将使用 branch..remote 和 branch..merge 选项中配置的上游(详见git-config(1))并假定--fork-point 选项.如果您当前不在任何分支上,或者当前分支没有配置上游,rebase 将中止。

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

    --fork-point 的行为并不是世界上最容易描述的,rebase 文档链接到the git merge-base documentation。它有一个很好的图表,但在描述方面仍有很多不足之处。

    因为--fork-point 依赖于 reflog,它只有在您的上游分支 reflog 保留关键信息时才有效。通常这是 90 天(可访问提交的到期时间)或 30 天(不可访问提交的到期时间)。这个does not make it any easier to describe. :-) 提及它的intent 可能会有所帮助:它旨在帮助从上游 rebase 中恢复,它确实做到了。

    【讨论】:

    • 虽然我已经很好地阅读了手册页,但我正要感到非常愚蠢。但是,我使用的 git 版本没有记录这一点。感谢您提供更好的解释!
    • 有一段时间,fork-point 在git pull 中很神奇,它根本不在 rebase 中。然后它被移动到git rebase,但没有记录。您必须拥有 Git 的过渡版本之一...
    【解决方案2】:

    我会留给比我更了解这个的人。但是在阅读了调用 rebase 的 git-rebase.sh 脚本后,我发现由于某种原因,--fork-point 在你调用 git rebase 时神奇地添加了没有参数。所以git rebasegit rebase --fork-point parent-branch 是一样的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-07
      • 1970-01-01
      • 2013-03-14
      • 1970-01-01
      • 2016-10-27
      • 2021-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多