在我的主分支中,我有两个文件:
file1.txt
file2.txt
我从那里创建了一个名为b1的新分支。在b1中,我修改了file2.txt,并意外删除了file1.txt(从磁盘,当我打开Windows资源管理器到源文件夹时,file1.txt不存在)。 现在我想保留file2.txt中的更改并从master恢复file1.txt(我不需要删除的版本)。我切换到master,做了一个合并到b1,没有发生冲突,它说'所有最新'但是file1.txt不存在。我该怎么做?Tks。
答案 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
。
在您的情况下,您需要取消合并:
git status
显示没有变化)取消您所做的合并
git reset --hard master@{1}
回到b1
git checkout b1
在工作副本中从主人结帐file1.txt
:
git checkout master -- file1.txt