我正在使用Git Extensions
,我的情况如下:
如您所见,我的目标提交不是最后一个。它已经被分支机构的其他用户推送和拉动。我读了一些关于通过git bash使用不同命令的文章来做一些工作,但在这里我发现了一种更简单的方法 - 我右键单击目标提交>操纵提交>弹出Fixup commit 并弹出另一个窗口。然后我能够更改提交消息(绿色部分),显然是为了推动更改,但我还没有做任何事情,因为从我读到的内容,这将导致其他用户的问题。科。
这些“问题”可能是什么?我如何修复提交+避免将来出现任何问题?
答案 0 :(得分:3)
注意:我不使用这些GUI,有时他们会做一些意想不到的事情。但在这种情况下,我希望它只能达到我的预期(因为它是:-))。
从根本上说,git实际上从未在提交中更改 任何。如果你做了#34;修改"操作,即使你不首先备份分支中的一个或两个提交,git下面的内容是进行新的提交,将旧的提交保留在repo中。
例如,您的提交链看起来像这样。我所做的只是以水平形式重写垂直图形版本(更适合文本)。
... - M - B - C - P <-- master, origin/master
/
...
其中M
是&#34;合并分支&#39; deploy&#34;提交,B
是第一个&#34;等等,等等#34;提交,C
是您要更改的,P
是推送提交(第二个&#34;等等,等等#34}。
现在,如果你&#34;分离&#34; HEAD
以便它直接指向提交C
,您可以运行命令行命令git commit --amend
,似乎它正在改变C
1}}。 Git使用原始提交消息调出一个编辑器,您可以更改文本并编写和退出编辑器,然后git进行新的提交。但它的作用是不&#34;改变C&#34;。相反,它会生成C
的副本,让我们将其称为D
,使用相同的文件但不同的提交文本。 (如果在执行git add
之前修改了某些文件和git commit --amend
,则对文件所做的更改将与新提交D
相关联;再次提交C
保持完全不变。)这会给你一个如下所示的提交链:
... - M - B - C - P <-- master, origin/master
/ \
... D <-- HEAD
现在可以进行提交P
并复制 it 。 (你仍然无法改变它 - 这是git提交的一个特性.Git提交永远被冻结:他们的SHA-1&#34;真实姓名&#34;是你名字的加密校验和提交作者,进行提交的时间戳,提交文本,提交的父提交,以及提交中的所有文件和目录;以及在提交中的任何位置更改单个位,更改SHA -1,因此提交的&#34;真实名称和#34;结果是一个新的,不同的提交。)让我们调用P
的副本(父级更改为{{ 1}})D
:
E
您的图形工具可以自动为您执行此操作,如果您说&#34;请更改提交... - M - B - C - P <-- master, origin/master
/ \
... D - E <-- HEAD
&#34;:它将复制C
,随着你喜欢的任何变化,变成C
;然后它将在D
之上复制事物 - 在这种情况下,这也意味着C
的副本。 (或者更有可能的是,它根本不会在P
&#34;之上发生任何事情,如果你愿意,可以强迫你这样做。)
您可以现在将您的本地分支标签C
移动到指向提交master
而不是提交E
。事实上,git有时甚至会帮助你做一些命令。 (我不知道你的GUI会做什么,我发现GUI很神秘,而且经常很烦人。:-))但是,如果你这样做,你将会有一个不同的&#34;分歧&#34; P
分支,因为远程仓库(master
的远程仓库)有您的提交origin
和C
(因为您已成功&#34;推送&#34;他们之前) 。它有它认为是P
分支的那些。
附注:如果您可以登录到机器master
,您可以在那里找到git repo并查看其对各种分支标签的看法。在那里,您将看到origin
指向提交master
。这就是为什么你的 repo拥有&#34;远程分支&#34;标签,P
,指向P:基本上,只要您的机器与遥控器联系,它就会问:&#34;嘿!你有什么标签?&#34;远程答案 - 可能会说&#34;我已经origin/master
和master
他们指向提交develop
和P
&#34; - 和然后你的git将这些复制到你的仓库,但更改了名称:Q
变为master
,origin/master
变为develop
,依此类推。这就是你怎么知道他所知道的。或者,更准确地说,你知道他所知道的,你最后一次与他交谈。那可能是秒之前,现在情况可能完全不同了!
无论如何,假设您将origin/develop
移至指向提交master
。如果您现在要求对E
进行push
这些更改,那么您的git会告诉他的git:&#34;嘿,我有这些新提交的D和E,你应该指出你的origin
到master
!&#34;他的git会看着那些并说:&#34;如果我这样做,我就会忘记提交E
和C
。您的提交P
返回E
,然后D
返回D
,B
和C
将无法访问。&#34 ;他的git会拒绝你的推动,除非你指定&#34; force&#34;选项。
如果你做指定&#34;强制&#34;,他的git可能仍会拒绝它,但可能他会接受它。这是一个&#34;坏事&#34;?也许。你会好的,P
的回购本身就可以了。但是,Joe在17秒前将你的提交origin
和C
从P
复制下来了怎么办?下次他去origin
时,他会期待origin
和C
仍然在那里,他们不会成为。乔必须弄清楚某人(你)&#34;倒退&#34;分支,&#34;删除&#34;提交P
和C
。
Git已经完成设置,并且每个人都希望能够处理新的提交以添加。他们通常不会期望旧的承诺去除#34;像这样。 Joe 可以修复此问题 - 他的回购仍然会有P
和C
; git实际上并没有删除提交(除非它们变得未被引用并被垃圾收集)。但他可能需要做很多工作来弄清楚你做了什么,并弄清楚如果他有新的东西,他已添加到P
,他现在需要复制那个添加到P
的新提交。 (具体来说,他必须确保他不会意外地复制提交E
和C
,这些提交现在归入P
和D
。)所以这可能会给Joe一个头痛。如果乔有这些,也许莎莉,弗兰克和艾琳也有这些承诺,也许你会给几十个人头痛。
不好吗?嗯,这取决于你的旧提交是谁,你通过这样做会给他们带来多少麻烦,以及你是否允许让他们头痛。 :-)如果没有人拥有它们 - 如果你的速度非常快,或者人们接受变化的速度你推动的是以天而不是秒来衡量 - 你会没事的。如果你给那些有你&#34;坏&#34;提出一些警告,他们知道该怎么做,你可以没事。如果没有,那么,谁知道?
答案 1 :(得分:1)
重写历史记录已被推送的问题是其他用户已经拥有&#34;原创&#34;历史,您的重写历史将不再兼容。因此,如果您更改倒数第二次提交(并且提交消息的更改足以执行此操作,因为消息是提交的哈希计算的一部分)并强制将其推送到服务器,任何工作其他人已根据该提交的旧版本已完成,或者任何较新的版本将不再适用(因为它在分支中不再具有有效的祖先)。正如这里指出的那样:RECOVERING FROM UPSTREAM REBASE
重新定位(或任何其他形式的重写)其他人根据其工作的分支是一个坏主意:下游的任何人都被迫手动修复其历史记录。
如果您要修复的提交是非常新的,并且其他任何人基于它做了很多的机会很少,请将交互式rebase,git push --force添加到服务器,并告诉其他贡献者git pull - 如果没有他们的本地更改,他们可以做。要根据重写的提交重新定义现有工作,请在此处查看已接受的答案:How do I recover/resynchronise after someone pushes a rebase or a reset to a published branch?。
这不是一站式解决方案,因为重写已发布的历史记录在设计上很麻烦。如果不是绝对必要的话,请不要这样做。
<强>备选方案:强> 我不知道你的错误提交信息是多么严重(完全是乱码,错误,不完整?),但是如果你只是需要澄清一些事情,你可以做到
git notes add -m"<Comment or clarification>" [commit-id-if-not-HEAD]
笔记是单独保留的,可以在以后更改/添加/删除,而不会影响历史记录。
答案 2 :(得分:0)
解决这个问题的几种方法(imho)最简洁的方法是在起源大师之上重新设置你的提交。
这可以这样交互式地完成:
git rebase -i origin/master