是否有一种快速的方法可以改变长期提交分支的历史?

Eki*_*bal 15 git rebase git-rebase

过去两周我一直在使用某个功能,我为它创建了一个单独的分支.问题是这个任务花了我很长时间,而且我没有定期修改我的分支.我最终提交了100多个提交,现在当我尝试将分支重新设置为使用时git rebase master,它需要永远,因为我需要检查每个提交的冲突,git add然后修改它git rebase --continue.

有更简单的方法吗?

abl*_*igh 14

这部分取决于您是如何完成100多次提交以及在此期间发生的事情.四种策略可能有用:

减少rebase的提交次数

如果你有一个100个提交的美丽清晰流,从不修改相同的代码两次,我很抱歉,但你被困住了.

但是,从两周内的100次提交中,我猜你的提交历史不是那样的.也许你已经在提交历史中修改了函数X 5次,并且每次提交都会导致冲突.如果只有一个修改函数X的提交,那么你将有20%的工作要做.

所以这里的答案是在你重新加入master之前整理你的提交历史.这是'git rebase'的另一个用途.将其重新定位到其现有基础上,但用于git rebase -i交互式压缩并重新排序提交.确保您拥有最少的提交数量,并且每个提交都是独立的.您也可以借此机会更改提交日志.密钥备份分支(git branch)和git diff每次提交后检查您没有更改任何内容的分支.

特别是,如果您有内部合并提交,则展平这些提示会很有帮助.

不可避免的是,当我这样做时,我发现我做错了,或者可能做得更好,即使它只是'代码格式化或提交消息'.您可以借此机会解决这些问题.我猜你应该在完成这项工作后提交10或20次提交 - 更易于管理.

重新分阶段

如果你已经这样做了,你可能不得不咬紧牙关.但是,如果同事在您工作期间一直在进行重构,有时您最好的做法如下.想象一下,树看起来有点像这样:

    A --- B --- C --- D --- E --- F -- .... -- X --- Y --- Z (master)
     \
      \----- 1 --- 2 --- 3 --- 4 .... 97 --- 98 --- 99 --- 100 (you)
Run Code Online (Sandbox Code Playgroud)

你最想做的是重新绑定到Z.但是,这会给你带来很多冲突.让我们假设提交D和E是来自同事重构你的代码正在处理的东西的两个巨型提议.有时候,它更容易:

  • 重新定位到C(这应该不是很多工作)
  • 深吸一口气,然后重新上到E上
  • 重新掌握到主人(这应该不是很多工作)

避免"主"方面的复杂性

有时,在您尝试合并的树上,事情变得非常复杂.一个典型的例子是(使用上面的图表),提交G恢复提交C,然后提交H重做(或几乎重做)它,并且同时有合并(特别是你可能已合并的东西) .谢谢同事,这使得变基变得非常简单.导致困难的其他因素是复杂的合并提交和令人讨厌的重命名.每次提交往往会一次又一次地给你相同的冲突,没有明显的理由.git rebaseAarrggh.

这里的一种技术是展平主树的副本,即分支主(本地),然后将整个东西压缩成从A到Z的单个提交.你也可以先把你的东西弄平(见上文).然后重新踩到扁平的主人身上.现在你已经获得了"正确"的提交,你可以很容易地将它们重新设置为master(因为代码完全相同,因此可以更改为'Z').

如果一切都失败了

有时git rebase似乎陷入了一种冲突的神游状态,现在是时候突破git format-patchgit am重新应用它.如果有人重命名了一个文件(因为你可以在你的编辑器中的补丁中修改文件名)或重命名一个公共类/变量/任何(你可以在补丁中找到/替换),这非常有用.

从错误中吸取教训

下一次,更频繁地重新加入主人.如果你继续这样做,那就不那么痛苦了.

此外,如果你有两个人在相同的代码区域工作并且它产生了一堆冲突,也许你的代码不够抽象,或者你可能在彼此之上工作并且可以更好地分工你的工作?


bau*_*aur 5

通过合并变基

让我描述一下我发现的方法。

我遇到了同样的麻烦,没有“只是合并”选项。而且我知道我们已经对-X他们的标志进行了重新标记,该标志可以自动解决所有与我们的更改产生的冲突,但是可以机械地起作用,并且我们正在丢失外部更改。

但是,如果我们可以添加一个额外的提交以从临时合并中恢复项目状态怎么办?我找到了一种简单的方法。

首先,签出临时分支并开始合并

git checkout -b temp
git merge origin/master
Run Code Online (Sandbox Code Playgroud)

您将必须解决冲突,但是只有一次,只有真正的冲突。然后暂存所有文件并完成合并。

git commit -m "Merge branch 'origin/master' into 'temp'"
Run Code Online (Sandbox Code Playgroud)

然后返回到您的分支(将其设置为alpha)并开始自动重新设置基准以解决所有冲突。

git checkout alpha
git rebase origin/master -X theirs
Run Code Online (Sandbox Code Playgroud)

分支已经重新设置了基础,但是项目可能处于无效状态。没关系,我们还有最后一步。我们只需要恢复项目状态,就应该像在分支“ temp”上一样。从技术上讲,我们只需要通过低级命令git commit-tree复制它的(文件夹状态)。加上合并到当前创建的分支中的提交。

git merge --ff $(git commit-tree temp^{tree} -m "Fix after rebase" -p HEAD)
Run Code Online (Sandbox Code Playgroud)

并删除临时分支

git branch -D temp
Run Code Online (Sandbox Code Playgroud)

就这样。我们通过隐藏合并进行了艰难的基础调整。

我还开发了一个脚本,因此可以以对话的方式完成,您可以在此处找到它。