ruo*_*ola 6 git git-merge git-rebase git-rewrite-history
很少提交,我不小心在我的master分支中进行了非线性合并。我习惯于一直尝试保持线性历史记录,因此现在我想恢复线性度。
我做了一个虚拟仓库,它模拟了我为了使其更简单而遇到的真实情况,这是它的GitHub链接:https : //github.com/ruohola/test-merge
这是的输出git log --oneline --graph --date-order:
* 88a4b7e (HEAD -> master, origin/master, origin/HEAD) 11
* 5aae63c 10
* 5506f33 Merge branch 'other'
|\
| * b9c56c9 9
* | 3c72a2a 8
| * 8d2c1ea 7
| * 35f124b 6
* | 7ca5bc1 5
* | b9e9776 4
| * fd83f02 3
|/
* 4fa8b2e 2
* cbdcf50 1
Run Code Online (Sandbox Code Playgroud)
Sourcetree中的相同图形:
这是mspaint可视化的图像,显示了我希望如何使我的主人看起来像:(
本质上应该像我在合并之前要重新设置基础)
我知道这可能不是最佳做法,并且我熟悉重写历史记录的后果(尽管没有人在此分支上工作),但仍然希望能够做到这一点。如何做到这一点?
ruo*_*ola 12
也许最简单的方法就是“滥用” 的默认行为git rebase。也就是说,如果没有显式传递--rebase-merges给git rebase,它实际上会从历史记录中删除所有合并提交。这使我们能够非常轻松地获得所需的结果:
前:
~/merge-question (master) $ git log --oneline --graph --date-order
* 88a4b7e (HEAD -> master, origin/master, origin/HEAD) 11
* 5aae63c 10
* 5506f33 Merge branch 'other'
|\
| * b9c56c9 9
* | 3c72a2a 8
| * 8d2c1ea 7
| * 35f124b 6
* | 7ca5bc1 5
* | b9e9776 4
| * fd83f02 3
|/
* 4fa8b2e 2
* cbdcf50 1
Run Code Online (Sandbox Code Playgroud)
运行命令:
~/merge-question (master) $ git rebase 3c72a2a
First, rewinding head to replay your work on top of it...
Applying: 3
Applying: 6
Applying: 7
Applying: 9
Applying: 10
Applying: 11
Run Code Online (Sandbox Code Playgroud)
后:
~/merge-question (master) $ git log --oneline --graph --date-order
* d72160d (HEAD -> master) 11
* 90a4718 10
* 3c773db 9
* ba00ecf 7
* 9e48199 6
* 24376c7 3
* 3c72a2a 8
* 7ca5bc1 5
* b9e9776 4
* 4fa8b2e 2
* cbdcf50 1
Run Code Online (Sandbox Code Playgroud)
此后,只需简单操作git push --force-with-lease origin master,遥控器的历史就恢复为线性。
eft*_*ft0 11
我认为这并不难,只要记住它需要重写 master 的历史:
git checkout b9c56c9
git rebase 3c72a2a # rebase on top of the other branch
git cherry-pick 5506f33..master # reapply changes from merge revision (dropping it) up until the tip of master
# if you like the results
git branch -f master
git checkout master
Run Code Online (Sandbox Code Playgroud)
现在,如果您已经在另一个远程服务器中拥有旧主服务器,则可以强制推送该分支
一种方法是使用 rebase。
无论您选择哪种方法,您都必须重写存储库的历史记录。你必须接受这一点,否则你将不得不接受你目前的历史。
让我们总结一下历史的不同部分:
为了解决这个问题,我将执行以下操作:
这是该过程的分步图(命令如下):
现在状态:
master
v
1---2---4---5---8---M--10--11
\ /
3---6---7---9
Run Code Online (Sandbox Code Playgroud)
9 人的新分支:
master
v
1---2---4---5---8---M--10--11
\ /
3---6---7---9
^
TEMP1
Run Code Online (Sandbox Code Playgroud)
在 8 之上变基,这将创建 3', 6', 7', 9'('意思是“提交的副本,相同的内容,新的散列”)
TEMP1
v
3'--6'--7'--9'
/
1---2---4---5---8---M--10--11
\ / ^
3---6---7---9 master
Run Code Online (Sandbox Code Playgroud)
为 11 创建一个新分支(我不喜欢和 master 搞混)
TEMP1
v
3'--6'--7'--9'
/
1---2---4---5---8---M--10--11
\ / ^
3---6---7---9 master
^
TEMP2
Run Code Online (Sandbox Code Playgroud)
将此分支(10 和 11)重新设置在 TEMP1 之上:
TEMP1 TEMP2
v v
3'--6'--7'--9'-10'-11'
/
1---2---4---5---8---M--10--11
\ / ^
3---6---7---9 master
Run Code Online (Sandbox Code Playgroud)
验证 TEMP2 与当前主站相同,没有丢失,没有添加,等等。
然后将 master 硬重置为 TEMP2:
master
v
TEMP1 TEMP2
v v
3'--6'--7'--9'-10'-11'
/
1---2---4---5---8---M--10--11
\ /
3---6---7---9
Run Code Online (Sandbox Code Playgroud)
然后我将删除分支 TEMP1 和 TEMP2。
请注意,提交 3、6、7、9、M、10 和 11 仍然存在于存储库中,但它们不能直接使用,因为没有任何引用它们。因此,它们有资格进行垃圾收集,实际上,您的存储库的实际历史现在看起来像这样:
1---2---4---5---8---3'--6'--7'--9'-10'-11'
^
master
Run Code Online (Sandbox Code Playgroud)
执行这些操作的命令是:
(第 0 步:制作本地文件夹的完整副本,包括工作文件夹和 .git 存储库,然后,如果可以,请在该副本中执行以下命令,如果出错,请删除副本并重新开始,不要没有安全网就跳)
git checkout <HASH-OF-9>git checkout -b TEMP1(是的,您可以在一个命令中执行此操作和上一个命令git checkout -b TEMP1 <HASH-OF-9>)git rebase -i --onto <HASH-OF-8> <HASH-OF-2> TEMP1git checkout -b TEMP2 <HASH-OF-11>git rebase --onto TEMP1 <HASH-OF-MERGE> TEMP2git checkout mastergit reset --hard TEMP2最后,清理:
git branch -d TEMP1 TEMP2
git push -f
Run Code Online (Sandbox Code Playgroud)
只有在您知道一切正常时才强制推送
| 归档时间: |
|
| 查看次数: |
152 次 |
| 最近记录: |