推送提交的更改是否会导致问题?

时间:2013-11-26 09:59:14

标签: git git-commit git-extensions

我正在使用Git Extensions,我的情况如下: enter image description here

如您所见,我的目标提交不是最后一个。它已经被分支机构的其他用户推送和拉动。我读了一些关于通过git bash使用不同命令的文章来做一些工作,但在这里我发现了一种更简单的方法 - 我右键单击目标提交>操纵提交>弹出Fixup commit 并弹出另一个窗口。然后我能够更改提交消息(绿色部分),显然是为了推动更改,但我还没有做任何事情,因为从我读到的内容,这将导致其他用户的问题。科。

这些“问题”可能是什么?我如何修复提交+避免将来出现任何问题?

3 个答案:

答案 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会做什么,我发现GU​​I很神秘,而且经常很烦人。:-))但是,如果你这样做,你将会有一个不同的&#34;分歧&#34; P分支,因为远程仓库(master的远程仓库)有您的提交originC(因为您已成功&#34;推送&#34;他们之前) 。它有认为是P分支的那些。


附注:如果您可以登录到机器master,您可以在那里找到git repo并查看其对各种分支标签的看法。在那里,您将看到origin指向提交master。这就是为什么你的 repo拥有&#34;远程分支&#34;标签,P,指向P:基本上,只要您的机器与遥控器联系,它就会问:&#34;嘿!你有什么标签?&#34;远程答案 - 可能会说&#34;我已经origin/mastermaster他们指向提交developP&#34; - 和然后你的git将这些复制到你的仓库,但更改了名称:Q变为masterorigin/master变为develop,依此类推。这就是你怎么知道他所知道的。或者,更准确地说,你知道他所知道的,你最后一次与他交谈。那可能是之前,现在情况可能完全不同了!


无论如何,假设您将origin/develop移至指向提交master。如果您现在要求对E进行push这些更改,那么您的git会告诉他的git:&#34;嘿,我有这些新提交的D和E,你应该指出你的originmaster!&#34;他的git会看着那些并说:&#34;如果我这样做,我就会忘记提交EC。您的提交P返回E,然后D返回DBC将无法访问。&#34 ;他的git会拒绝你的推动,除非你指定&#34; force&#34;选项。

如果你指定&#34;强制&#34;,他的git可能仍会拒绝它,但可能他会接受它。这是一个&#34;坏事&#34;?也许。你会好的,P的回购本身就可以了。但是,Joe在17秒前将你的提交originCP复制下来了怎么办?下次他去origin时,他会期待originC仍然在那里,他们不会成为。乔必须弄清楚某人(你)&#34;倒退&#34;分支,&#34;删除&#34;提交PC

Git已经完成设置,并且每个人都希望能够处理新的提交以添加。他们通常不会期望旧的承诺去除#34;像这样。 Joe 可以修复此问题 - 他的回购仍然会有PC; git实际上并没有删除提交(除非它们变得未被引用并被垃圾收集)。但他可能需要做很多工作来弄清楚做了什么,并弄清楚如果他有新的东西,他已添加到P,他现在需要复制那个添加到P的新提交。 (具体来说,他必须确保他不会意外地复制提交EC,这些提交现在归入PD。)所以这可能会给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