gpt4 book ai didi

git - 修复 GIT 存储库上的历史记录

转载 作者:太空狗 更新时间:2023-10-29 13:43:16 26 4
gpt4 key购买 nike

我的 GIT 存储库中有以下情况。有人在做他的更改之前忘记 pull master,然后提交给他的本地 master。之后,出于某种原因,他将 origin/master merge 到他的本地 master 中,然后将其推送。结果是原点/主人与他本地的主人有点“互换位置”。我说的有道理吗?
下面是一个例子:

推之前

x----x-----x----x----x----x----x-----x----x (MASTER)

推后
 ---------------------------------------------x---x (MASTER)
| |
x----x-----x----x----x----x----x-----x----x-------

这有点弄乱了存储库,因为现在所有的历史记录似乎都在一个分支上。

在那之后,有一些新的提交被推送到了新的 master,然后由于一个现在并不重要的原因,我们决定我们不想要那些,所以我们设法删除了我们不想要的提交,并且同时将 de MASTER 恢复到原来的位置。像这样:


 ---------------------------------------------x---x---x---x---x (MASTER)
| |
x----x-----x----x----x----x----x-----x----x-------


                                             (2)
---------------------------------------------x---x---x---x---x--
| | |
x----x-----x----x----x----x----x-----x----x-----x----------------x (MASTER)
(1) (3)

如您所见,现在由忘记 tu pull 的人提交的提交已 merge 到最初的 master 中。这是这样实现的:
git checkout <HASH OF COMMIT MARKED AS (1) >
git checkout -b refactor_master
git merge --no-ff <HASH OF COMMIT MARKED AS (2) >
git push origin refactor_master
git merge --strategy=ours mastergit checkout master
git merge refactor_master
git push origin master

这有效地使这些提交所包含的更改从 master 中消失了,并且也将 master 变成了以前的样子。但是,我现在有一个不应该存在的“分支”。实际上,标记为 (3) 的最后一次提交没有进行任何更改。它只是“切换”了主人。有没有办法让这些提交消失?

最佳答案

这确实有道理:他的所作所为违反了“发展的主线是第一 parent ”的规则。

请注意,git 本身没有任何东西可以强制执行此规则。这是不可能的,原因很简单:谁定义哪条线是“主线”?这个问题唯一可能的答案是“你”,其中“你”的意思是“任何运行 git 来操作提交图的人”。所以这并不是真正的 git 规则,而是“使用 git 的人”规则。

无论何时运行 git merge (或者在这种情况下,“他”运行它),您选择您当前的分支作为开发的主线,并将您正在 merge 的任何内容作为正在 merge 的备用线路。因此,如果你这样做:

$ git checkout master
$ make-some-change; git add ...; git commit -m message

$ git fetch origin # and let's assume this brings in a new commit
$ git merge origin/master

您告诉 git 将您的 master 作为主线,并将上游更改 merge 为分支线。

注意最后两个命令—— git fetch其次是 git merge ——是什么 git pull默认情况下。反过来,这意味着“主线是第一父级”很常见,除非您非常严格/小心,否则不能依赖。

Is there any way to make those [merge] commits disappear?



是的,但只能通过编写新的提交行(“重写历史”)。

让我拿你的最终图(不用担心你是怎么得到的)并对绘图做一些小的改动以获得更紧凑的表示:
  ------------------------A---M1--B--C--D
/ / \
o--o--o--o--o--o--o--o--o---x-------------M2 <-- master

提交 B通过 D在这一点上是“在错误的线上”,因为 merge 提交的第一个父级 M2x ,它的第二个父节点是 D .同时提交 AM1 的第一个父节点和 xM1的第二个 parent 。

如果你真的很在意第一父级规则,你可以在提交 x 之后创建一行新的提交。 :
  ------------------------A---M1--B--C--D
/ / \
o--o--o--o--o--o--o--o--o---x-------------M2 <-- master
\
A'--B'--C'--D' <-- new-master

这里 A'的第一个也是唯一的父级提交 x ,这是 master 的提示提交当事情第一次“出错”时,就像它一样。然后 B'的第一个也是唯一的 parent 是 A',依此类推。

如果,一旦你有了这张图,你从白板上抹去提交 A通过 M2并制作 master指向提交 D' ,你会得到这个:
o--o--o--o--o--o--o--o--o---x
\
A'--B'--C'--D' <-- master

现在您可以“理顺”来自 x 的链接至 A'它看起来像一个很好的线性历史。

不过,这是棘手的部分:这只是您想要的图表。对于图中的每个提交,git 都会保留一棵树:一组文件,当您 git checkout 时将其放入您的工作目录中。那个提交。每次提交所需的树 A'通过 D'可能与 A 上的原始树不完全相同通过 D .

很确定你想要的树 B' , C' , 和 D'将与您在 B 中使用的相同, C , 和 D分别。但是,新提交所需的树 A'可能是目前正在 merge 的那个 M1 .这可能与提交 A 下的相同,但可能不是。这真的取决于如何 A比较 M1 .

有很多相对棘手的方法可以在没有大量手动工作的情况下构建新提交,但它们很难用文字描述。另外,这种“历史改写”——强行改旧的部分 master标签指向 new-master的提交 D' — 给所有正在提交的开发人员带来痛苦 M2作为他们的 parent 提交。他们必须使用新的 D' 将这些提交复制到新的提交中。作为他们的 parent 。

这种痛苦是否值得取决于你和他们。

关于git - 修复 GIT 存储库上的历史记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28177476/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com