当我设置我的分支时,我做了:
git svn rebase
git checkout -b branch-a
然后我将该分支推送到远程git存储库和一位同事,我使用git commit
,git pull
和git push
对其进行了处理。
现在,我想从subversion中提取所有新的更改,所以我做了:
git checkout master
git svn rebase
git checkout branch-a
git rebase master
此时我很困惑。似乎发生的事情是git会在一次或多次冲突中提交并迫使我解决它们。然而,冲突似乎是git让HEAD指向树的尖端(使用最新的代码),然后尝试在顶部上逐个应用每个更改,就好像它将它们应用于原始分支点。
感觉我再次重写所有代码,大部分解决方案是保留HEAD块并摆脱提交块。
我的期望是git rebase master
命令将在分支之前的提交处开始,从master添加每个提交,然后在分支上添加每个提交。然后,这将在分支上产生几乎与变形前相同的尖端。
那么,任何人都可以解释我未能理解的内容。
如果做不到这一点,任何人都可以建议如何找出为什么git决定这样做。我会在git log
中寻找什么,看看为什么会这样做。
编辑:2012-03-06
进一步的研究表明,我们似乎在我们的分支和分支结构中有多个提交的多个副本,来自git log --graph
,当我们认为只有一个时,它显示了多个分支。
一个片段(标识已删除的细节和提交消息已替换为message- n 。消息 - n 指的是相同的消息):
| * | commit f5c48df66ed9d733364562d8f125866aa6483c1e
| | | Author: commiter-b
| | | Date: Mon Feb 27 16:18:05 2012 -0800
| | |
| | | Message-4
| | |
| * | commit e6115229e629c237b08d0b2e149353f33ff66bd1
| | | Author: commiter-a
| | | Date: Mon Feb 27 15:49:02 2012 -0800
| | |
| | | Message-3
| | |
| * | commit f85981736c59231dc34a7cef4fceab5cffdbdff2
| |/ Author: committer-a
| | Date: Mon Feb 27 14:20:56 2012 -0800
| |
| | Message-2
| |
| * commit b09ba82e6290f5905d4c98fdcfbe2220d221e762
| Author: committer-a
| Date: Mon Feb 27 14:04:13 2012 -0800
|
| Message-1
|
* commit 4d2892c239acfab5c9845518fde98ba551f273e6
| Author: committer-a
| Date: Mon Mar 5 09:13:19 2012 -0800
|
| UN-3710 Fixes after merge from svn
---8<----- snip
* commit 8307d1ae8214ebe3eac5bdc5b835c21f89d727bd
| Author: committer-b
| Date: Mon Feb 27 16:18:05 2012 -0800
|
| Message-4
|
* commit 859acc56de59877cb721914443c63ad97882cb41
| Author: committer-a
| Date: Mon Feb 27 15:49:02 2012 -0800
|
| Message-3
|
* commit 93e15921d735333194970cefc673a8b953e80838
| Author: committer-a
| Date: Mon Feb 27 14:20:56 2012 -0800
|
| Message-2
|
* commit 7a863bb44be5c5019a0e0958460324dc3cfb2e6b
Author: committer-a
Date: Mon Feb 27 14:04:13 2012 -0800
Message-1
我相信,我们的git工作流程是保守的。我们使用git-svn
来维护被推送到远程git存储库的master
。我们使用master
和git pull origin branch-a
分支git push origin
,两个或多个提交者就可以使用它。
既然我们已经注意到问题的这个特征,我们将来会仔细观察它会导致什么事件发生。
答案 0 :(得分:5)
首先,快速总结一下git rebase
的作用。
如果您的历史记录如下:
trunk branch
| /
B C
| /
|/
A
|
|
当你git rebase trunk
时branch
,这就是你得到的:
trunk/branch
|
C
|
B
|
A
|
|
这就是为什么它被称为rebase
- branch
的前一个 base 是提交A
- 这就是它与“上游”分开的点分支,trunk
。操作后,新基数为B
,HEAD
的较新trunk
。你重新做了它。
git svn rebase
只是自动执行此操作,将您所做的更改移植到来自SVN的新提交中。
现在,有一个问题。 git-svn
,对于歇斯底里的葡萄干,不使用git笔记来存储其元数据。相反,它会重写提交对象本身,在每个提交消息的末尾添加git-svn-id
行。这会导致每个提交的SHA1标识符发生更改。因此,即使是相同的提交也是不同的 - 并且可能与他们自己的替代宇宙版本冲突!
当您尝试从git rebase master
branch-a
branch-a
时,您可能会看到这种情况:master
与先前状态{{{}}的某些非承诺到SVN版本不同1}},所以现在当你尝试合并时,你会在双方都改变的事情之间产生冲突。
这是git-svn
的限制:一旦您将更改推送到SVN,您必须小心只使用提交的推送到SVN重写版本。您不能混合预先提交的表单和提交后的表单,因为它们具有相同内容的“不同”更改。
您可以通过检查从git merge-base master branch-a
到master
和branch-a
的更改来验证这是您尝试执行的操作。您可能会在双方看到相同的变化。
要在这种特殊情况下让自己摆脱困境,请删除您的分支,从master
创建一个新分支,然后git cherry-pick
按顺序branch-a
创建更改,省略其中master
已包含。将来,要更加谨慎地使用尚未进入SVN的版本......