git:git恢复的更好方法,无需额外的恢复提交

git:git恢复的更好方法,无需额外的恢复提交,git,revert,Git,Revert,我在远程+本地分支中有一个提交,我想将该提交从历史记录中删除,并将其中一些提交到自己的分支中 基本上,现在我有: D---E---F---G master 我想: E---G topic / D master 这应该在我的本地存储库和远程存储库中(只有一个称为源存储库) 哪种方法最干净 此外,还有其他人克隆了该回购协议,并签出了主分支。如果我在远程回购中做这样的更改,“git-pull”是否也能让他

我在远程+本地分支中有一个提交,我想将该提交从历史记录中删除,并将其中一些提交到自己的分支中

基本上,现在我有:

           D---E---F---G master
我想:

             E---G topic
            /
           D master
这应该在我的本地存储库和远程存储库中(只有一个称为源存储库)

哪种方法最干净


此外,还有其他人克隆了该回购协议,并签出了主分支。如果我在远程回购中做这样的更改,“git-pull”是否也能让他们达到相同的状态?

如果你愿意,你可以重写你的历史记录,但如果其他人有历史记录的副本,这是个坏主意。在本例中,您可能会使用交互式rebase:
git rebase-i master topic
。这将为您提供从主机到主题的提交列表,并提示如何使用它们。您只需要删除包含要删除的提交的行

尽管如此,我必须强调,如果其他任何人有这样的历史,那么这样做是不负责任的。您必须强制将其推送到您的中央回购,其他人必须修复其存储库以进行匹配,这可能相对简单,也可能相对复杂,具体取决于具体情况

如果你真的决定这样做的话,在讨论如何处理这一问题时,有一个很好的章节叫做“从上游返利中恢复”

编辑:

对于简单的历史记录,常见的情况是,在强制向中央回购进行非快进推送(
push-f
)之后,其他开发人员:

  • 备份他们的旧主机:
    git分支-m master master\u old
  • 从源站获取更新并重新创建主机:
    git远程更新源站;git分支主控源/主控
  • 将所有主题分支重新设置到新主主题上:
    git-rebase——设置到主主题上\u旧主题上

如果他们在其主分支中有尚未起源的工作,他们将不得不变得更加有趣,将此工作和所有主题分支重新定位到主分支的新位置上。。。这应该会让你明白为什么重写别人的历史如此糟糕。事实上,一旦某些内容被传递到公共存储库中,您应该将其视为硬记录的历史,而不是正在进行的工作。

如果您已经发布,那么您不想重新编写
master
的历史是对的。您想要的是发布一个commit to master,将其恢复到
D
的状态,同时保留其当前历史记录,以便其他用户可以轻松合并或重新设置其工作的基础

如果您计划在将来的某个时候将
主题
合并到
中,那么您可能还想做的是在
主题
之间建立一个新的公共基础,以便在随后合并
主题
时,您不会丢失在
master
中还原的提交。最简单的方法是在将
master
重置回其原始状态的“undo”提交的基础上进行“redo”提交,并在此基础上建立新的
topic
分支

# checkout master branch (currently at G)
git checkout master

# Reset the index to how we want master to look like
git reset D

# Move the branch pointer back to where it should be, leaving the index
# looking like D
git reset --soft HEAD@{1}

# Make a commit (D') for the head of the master branch
git commit -m "Temporarily revert E, F and G"

# Create the new topic branch based on master.
# We're going to make it on top of master and the 'undo'
# commit to ensure that subsequent merges of master->topic
# or topic->master don't merge in the undo.
git checkout -b topic

# Revert the undo commit, making a redo commit (G').
git revert HEAD
作为替代方案,您可以让提交E',F'和G'分别重做每个部分,但由于E,F和G已经出现在您发布的历史记录中,如果您只是引用“撤消”提交并说该提交正在撤消,可能更容易理解。无论如何,这就是git revert所做的

基本上你知道的就是这个

D -- E -- F -- G -- D'      <-- master
                     \
                      \
                        G'  <-- topic

D--E--F--G--D'我发现
git stash
非常有用


把它藏起来,不要再看了。

好的,非常感谢你提供的信息。所以这并不是一个真正的解决方案,因为我不想做这样的力推。要得到类似的结果,最干净的解决方案是什么?我现在想的是在master中恢复E,F,G,然后从该状态创建一个新分支,然后选择E和G。这是一种自然的做法吗?如果不引起此类问题,就无法从历史中删除提交。无论你做什么,你最终都会将你的master ref指向一个在其历史中没有master先前位置的提交。这在我对这个问题的新版本的回答中得到了很大的解决,但要回答你的评论:你如何进入重写master历史的状态并不重要。你仍然会重写它。如果你在当地做这些事情,那就好了。这叫做清理。如果你对已发表的作品做这些操作,你就把事情搞砸了,创建了一个没有人可以信任的公共回购协议,等等。通过还原E、F、G,我想使用git revert。所以历史看起来有点丑陋,但我不需要处理这些问题,因为我真的不想改变已经推动的历史。啊,好吧。对不起,我误解了你的意思,以为你在说把师父指给樱桃树摘的那一套。如果你想创建新的分支,你仍然可以使用相同的重基方法——只需在master new上创建,而不是master。谢谢,这正是我现在所做的(也是我在给Jefromi的一些评论中建议的)。历史现在有点难看,因为这个撤销提交,但我不能做任何事情。2周git用户在这里。首先将G分支到G',然后
git恢复到
G到D,从而得到D',不是更容易吗?这样你就不必撤销/重做任何事情,这对我来说安全多了。(我已经无法恢复地丢失了编辑,因为我弄乱了
git reset
)@bart,看看
git reflog
。被提交并随后被破坏的内容应该总是可以通过reflog恢复,至少在几天内是这样。然而,您可能无法恢复地丢失您未能提交的更改。@bart,Charles Bailey解释了为什么他会按照他在这里所做的顺序来做事情,他说“您可能还想做的是创建一个新的公共文件。”