首先,我真的不明白这是怎么发生的,其次,我可以撤消这个吗?
为了说明这一点,网络现在看起来像这样:
local-develop ---------------------------------- C*--- M -
origin/develop --- C --- C --- C --- C --- C --------- /
我真正想要的是C *将被提交到origin / develop而不是合并分支。
正如我所说,这已经被推了。有没有办法删除更改并以我想要的方式提交它?
例如我做:
git reset --hard HEAD~1
我不确定这是否会撤消合并,我有两个不同的开发,然后合并删除等...?
答案 0 :(得分:26)
合并不会在推送时发生,它们发生在git merge
上(好吧,pull
但这真的只是获取+合并,因此合并时会发生合并)。
你似乎更有可能做到这样的事情:
<get copy from origin/develop>
<wait around for remote's origin/develop to acquire new commits>
git checkout develop # get onto (local) develop branch
<edit>
git commit -m message # create some new commit(s)
git push origin develop # attempt to push -- but this fails!
git pull
这是创建合并提交的最后一步(上面M
),因为pull
表示fetch
(获取现在位于{{1}的所有新提交}}),然后origin/develop
(带你的本地merge
并将你的提交与那些刚刚提取的新提交合并。)
如果您没有develop
这个新的结果,那么远程仓库 你的本地提交,您已标记为git push
和C*
的人。在这种情况下,你的身体状况良好! (您可以再次运行M
进行检查,以确保您的本地回购git fetch
与遥控器中的origin/develop
匹配,然后执行git log origin/develop
以查看其中的内容。)
可能有助于记住,这里有两个完全独立的git回购:你的,你的东西;以及你在这里打电话origin
的人。 (让我们调用该机器X
。)如果您要登录X
,它有自己独立的提交历史记录和分支名称等等。在那里,您可以将目录更改为repo,运行git log -1 develop
,并查看该分支顶端的内容。
现在,如果您从X
注销并重新使用自己的计算机,则可以运行git log -1 origin/develop
。如果这与您在X
上看到的内容相同,则get fetch
无需更新,因为git fetch
的作用实际上(但更有效),登录到X
并查看develop
中的X
内容。 origin/develop
fetch
中origin/develop
所带来的X
所带来的任何内容都会带来并添加到X
。现在,您与merge
同步。 pull
没有你的东西,但你有他们的东西。
如果你再采取额外的步骤develop
(包括X
暗示的那个),git将会(如果必须的话)进行合并提交......但所有这些都是在你的回购中,在分支的顶端(在这种情况下仍为X
)。除非并且直到你将此合并提交推送到X
(或者X
上的某人提取你的提交但是暂时忽略它:-)),rebase
赢了&# 39;没有。
无论如何,只要遥控器(develop
这里)没有你的合并提交,你就是金色的。由于他们没有它,其他人也没有。您可以C*
origin/develop
M
分支将您的提交(origin/develop
)置于X
之上。这将摆脱合并提交(pull
),然后你可以将一个简单的快进推送到X
。
如果X
有你的合并提交 - 即,如果你在git reset
之后推动并获得了合并 - 那么你就会被卡住(对某些人而言)因为可能其他人有权访问git rebase
并且现在正在使用您的合并提交。可以回滚X
上的回购,类似于您在自己的回购邮件中使用devel
和--------------------------- C*--- M
--- C4 --- C5 --- C6 --- C7 ---- /
执行此操作的方式,等等,但是&#39} ; s通常是一个坏主意。
X
上),但是你绝对确定没有其他人看到你的更改,而且你&#39;肯定会重置它们,而不是将它们还原(将数量恢复为&#34; fesing up&#34;并留下螺旋记录,这让其他人可以轻松地从中恢复,但也让他们看到你的错误: - ))。 1
这就是诀窍:你首先需要让机器X的回购说#34;分支cd
的提示是C7&#34;,其中C7在你的来自前面的非常自己的图表,只是重新编号,以便我可以区别地命名每个提交:
--bare
那么,你怎么能这样做?好吧,一种方法是在git update-ref
, 2 50db850
登录回购(即使它是localhost$ ssh X
X$ cd /path/to/repo.git
X$ git update-ref refs/heads/develop 50db850
),然后使用{{ 1}}那里。让我们说C7的SHA1实际上是X
(如&#34; git log&#34;所示)。然后你可以这样做:
git push -f
但是,如果您无法登录origin/develop
,或者甚至根本不想登录,则可以使用push -f
执行相同操作。 3 (这还有其他优点:特别是,一旦localhost$ git branch resetter 50db850
localhost$ git log resetter # make sure it looks right
...
localhost$ git push -f origin resetter:develop
Total 0 (delta 0), reused 0 (delta 0)
To ssh://[redacted]
+ 21011c9...50db850 resetter -> develop (forced update)
localhost$ git branch -d resetter # we don't need it anymore
成功完成,你的git repo就会知道push -f
已被重绕。)只需创建一个指向正确提交的本地分支:< SUP> 4
M
完成此操作后,机器X将恢复到您想要的状态,您就可以继续进行,就好像您从未推动过您不喜欢的合并一样。
请注意,当您执行lost+found
时,如果其他人在git fsck --lost-found
之上进行了新的提交,那些也将变得不可见(从技术上讲,他们是&#39;仍然在那里,伴随着你的合并提交,但它们在git log
意义上git ls-remote
失去了#34;并且在几个月之后它们真的会永远消失)。 5
再次和非常重要:这种共享回购&#34;回滚&#34;对于共享仓库的其他用户来说是一个巨大的痛苦,所以在你做之前要确定它没问题。
1 这种微不足道的合并甚至不需要还原。将合并留在那里没有根本的错误。但是,如果你正在处理一个更严重的错误合并,除了你的&#34; oops&#34;的记录之外,恢复合并还有另一个缺点:它会重做&#34;重做& #34;后来的变化有点困难,因为后来的&#34;目的合并&#34;会看到之前的合并并认为:好的,我不需要重新合并那些更改。然后你必须&#34;恢复还原&#34;代替。
我认为这里正确的外卖课程是:在推前查看(git push -f
)以确保您要推送的内容是您打算推送的内容。< / p>
2 或者,更简单,更简单:{{1}}。这使用获取协议代码来查看远程具有的内容。但它隐藏了我要去的主题,那就是:遥控器就像你的一样!//
3 即将发布的git版本2发布了新的&#34;安全功能&#34;这将与{{1}}一起使用。但是他们还没有出来,所以这对你没有帮助。我会在以后重新编辑它,以便注意它们。在那之前,真的在这里小心点:此时你正试图将其他东西推向共享存储库。
4 您甚至可以通过原始SHA-1 ID执行此操作。分支名称更容易连续多次正确输入。
5 保留和到期是通过git&#34; reflogs&#34;。共享服务器可能没有记录所有ref更新;如果没有,只有已经有新提交的私有回购将保留它们。对于不再可从分支提示到达的提交,最短的默认到期是30天,即大约一个月。但请注意,这是一个无趣的,疯狂的争夺,让每个人都可以通过他们的存储库搜索&#34;丢失&#34;在强行推动&#34;失去工作后承诺&#34;关闭共享存储库。
答案 1 :(得分:1)
Linus Torvalds在此回复Linus Torvalds的回复http://opensource.apple.com/source/Git/Git-26/src/git-htmldocs/howto/revert-a-faulty-merge.txt