将已删除文件的分支合并回master

时间:2012-09-26 09:28:48

标签: git version-control

在我的主分支中,我有两个文件:

file1.txt
file2.txt

我从那里创建了一个名为b1的新分支。在b1中,我修改了file2.txt,并意外删除了file1.txt(从磁盘,当我打开Windows资源管理器到源文件夹时,file1.txt不存在)。 现在我想保留file2.txt中的更改并从master恢复file1.txt(我不需要删除的版本)。我切换到master,做了一个合并到b1,没有发生冲突,它说'所有最新'但是file1.txt不存在。我该怎么做?Tks。

2 个答案:

答案 0 :(得分:11)

我认为你在这里有几个问题。第一个似乎是“如何恢复file1.txt?”假设您的修订图看起来像这样:

               M
(master)  o -- o --- o ------o  HEAD
                \           /
(b1)             o -- o -- o
                 A    B    C

您可以通过file1.txt获取git checkout的上一份副本:

git checkout HEAD~1 -- file1.txt

这会复活file1.txt并将其放入您的工作副本中。您可以git commit和文件返回。注意:HEAD~1表示取HEAD的第一个父项,它指向合并b1之前的master状态。如果您知道提交ID,则可以使用它而不是HEAD~1

你似乎要问的另一个问题是“我应该在分支b1中做些什么才能避免这种情况?”最明显的选择不是首先删除file1.txt。但是我们假设你认为你需要,并认为选择是错误的。接下来,让我们假设您没有通过在某处推送更改来共享分支b1。如果您发现自己立即删除了该文件,则可以执行以下操作:

git checkout HEAD~1 -- file1.txt
git commit --amend

那就是说,“给我回复file1.txt,然后将该文件合并到最新的提交中。”这样做的效果就像你从未删除过的文件一样。

如果您没有注意到该文件已立即删除,并且您之间有多次提交,那么您可能希望使用git rebase来解决问题。

如果您在其自己的提交中删除了该文件,则可以使用git rebase -i从分支的历史记录中删除提交。我们假设B是删除文件的提交,这是该提交中唯一完成的事情。在b1上,你会运行类似:

git rebase -i B~1

删除包含违规提交(B)的行,保存并退出。您的分支刚刚在没有B的情况下重写了它的历史记录。例如,我运行git rebase -i,这在编辑器中显示:

pick 40f76a7 removed bar
pick 30a25f5 modified foo

然后我从列表中删除了40f76a7然后离开了我:

pick 30a25f5 modified foo

合并后,历史记录现在如下所示:

               M
(master)  o -- o --- o ------o  HEAD
                \           /
(b1)             o ------- o
                 A         C'

请注意C'的提交ID与C不同,因为B不再存在,并且父sha1是提交ID的一部分。 IOW,C的sha1改变了,因为我们重写了历史。

如果您删除了file1.txt并在同一次提交中进行了一系列其他更改,那么还有一些步骤。首先,恢复文件并提交它:

git checkout B~1 -- file1.txt
git commit -m "Reinstate file1.txt"

让我们调用新的提交D。我们的修订图现在看起来像

               M
(master)  o -- o --- o -----------o  HEAD
                \           
(b1)             o -- o -- o -- o
                 A    B    C    D

现在,做:

git rebase -i B~1

将包含提交ID D的行移至提交ID B之后,并将pick更改为squash。例如,我在运行git rebase -i B~1

时得到此信息
pick 40f76a7 removed bar plus other changes
pick 30a25f5 modified foo
pick 6177cb7 add bar

6177cb7是恢复bar的提交。所以我将它移到40f76a7下方并将命令更改为squash

pick 40f76a7 removed bar plus other changes
squash 6177cb7 fix bar
pick 30a25f5 modified foo

保存并退出。它会要求您修复提交消息。去做。完成所有工作后,您最终得到的结果如下:

               M
(master)  o -- o --- o -----------o  HEAD
                \           
(b1)             o -- o -- o
                 A    B'   C'

新的B'不再删除file1.txt。此时,您已准备好与master合并。

几句结束语。小心git rebase。如果你不小心,你可能会失去历史。请务必阅读git rebase手册页。那里有很多有用的信息。注意:如果要删除从历史记录中删除文件的事实,则git rebase所有这些工作只需。如果您可以通过提交显示回来文件,那么请务必使用git checkout恢复文件并提交。对于新的git用户来说,它不那么乏味,而且更容易。 git rebase非常先进,需要一些练习。但是,如果你花时间学习并且学得很好,那真的非常有用。

答案 1 :(得分:3)

合并不是你在这种情况下做的事情,Git在合并回master时保留删除是正常的。如果您想从另一个分支或标记中获取文件,则为git checkout master -- filename

在您的情况下,您需要取消合并:

  1. 确保您使用的是主人,并且您的工作目录是干净的(git status显示没有变化)
  2. 取消您所做的合并

     git reset --hard master@{1}
    
  3. 回到b1

    git checkout b1
    
  4. 在工作副本中从主人结帐file1.txt

    git checkout master -- file1.txt
    
  5. 提交或修改您之前的提交,或任何您想要做的事情