git checkout不会删除应该删除的文件 [英] git checkout is not removing files that it should

查看:384
本文介绍了git checkout不会删除应该删除的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用公共仓库,我想让我的master分支回到过去的某个提交.我已经检查了选项,对我来说,最好的事情是对所需的提交进行简单的签出,然后提交到master分支.但是,当我执行检出操作时,它不会删除在指定的提交哈希之后已添加到master中的某些文件.

例如,如果我想回到提交aaa1:

$ cd working-copy-top-dir
$ git checkout master
$ git checkout -- .
$ git clean -fd
$ git checkout aaa1 .
$ git clean -fd

但是,此时,在aaa1之后添加的某些文件仍在工作副本中. checkout命令如何将工作副本 data 恢复为aaa1的状态?

$ git --version
git version 2.7.2.windows.1

解决方案

TL; DR:先删除所有内容

使用git checkout aaa1 .时,您告诉Git将aaa1转换为提交,找到该提交(更确切地说是其树),然后将该提交中的每个文件复制到索引/暂存区和工作树中

为了便于讨论,让我们假设从master开始,其中包含两个文件READMEhello:

$ git checkout master
[output snipped]
$ ls
README   hello
$ cat README
Yay, you read me!
$ cat hello
world
$ 

让我们进一步说,提交aaa1存在并且其中有两个文件READMEaddendum.它的READMEThank you for reading.让我们进行结帐:

$ git checkout aaa1 -- .
[output snipped]
$ ls
README    addendum  hello

(我添加了--:此处实际上不是必需的,但这是一个好习惯.)README的内容是更新的README.文件addendum也已被提取. hello文件未删除 ,并且与master中找到的版本保持不变.分阶段更新的READMEhello:

$ git status --short
M  README
A  addendum

但未删除hello:

$ git ls-files --stage
100644 ac6f2cf1acbe1b6f11c7be2288fbae72b982823c 0   README
100644 7ddf1d71e0209a8512fe4862b4689d6ff542bf99 0   addendum
100644 cc628ccd10742baea8241c5924df992b5c019f71 0   hello

即使使用-x,使用git clean也将无效:不需要清洁.没有未暂存的文件(hello已暂存,只是未进行修改).


您特别想要获取工作树以匹配提交aaa1,一个字节一个字节地匹配.为此,您必须找到现在在索引中但不在aaa1中的文件,然后将其删除.

但是,有一种更简单的方法:只需删除所有内容.然后,使用git checkout aaa1 -- .aaa1中提取所有内容.这将从aaa1填充索引和工作树:所有需要恢复到删除之前的文件的方式都将被恢复(恢复为它们在aaa1中的方式,它们与相同作为它们在HEAD中的方式).所有需要更改以匹配它们在aaa1中的方式的文件(将恢复为它们在aaa1中的方式,这是不同的).

$ git rm -rf .
rm 'README'
rm 'addendum'
rm 'hello'
$ git checkout aaa1 -- .
$ git ls-files --stage
100644 ac6f2cf1acbe1b6f11c7be2288fbae72b982823c 0   README
100644 7ddf1d71e0209a8512fe4862b4689d6ff542bf99 0   addendum
$ git status --short
M  README
A  addendum
D  hello

您现在可以提交,并且在master上将有一个新的提交,无论之前有什么,其提交都与aaa1完全相同.

(这是否是一个好主意,完全是另一回事,但是它将为您提供所需的状态.)

Using a public repo, I want to get my master branch back to a certain commit from the past. I have reviewed the options and the best thing for me looks to be a simple checkout to the desired commit, then commit to the master branch. However when I do the checkout it does not remove some files that have been added into master after the specified commit hash.

So for example, if I want to get back to commit aaa1:

$ cd working-copy-top-dir
$ git checkout master
$ git checkout -- .
$ git clean -fd
$ git checkout aaa1 .
$ git clean -fd

But at this point some files added after aaa1 are still in the working copy. What is the checkout command to get the working copy data back how it was at aaa1?

$ git --version
git version 2.7.2.windows.1

解决方案

TL;DR: remove everything first

When you used git checkout aaa1 ., you told Git to translate aaa1 to a commit, find that commit (more precisely, its tree), and copy every file in that commit to your index / staging area and work-tree.

Let's say, just for the sake of argument, that you start with master containing two files, README and hello:

$ git checkout master
[output snipped]
$ ls
README   hello
$ cat README
Yay, you read me!
$ cat hello
world
$ 

Let's say further that commit aaa1 exists and has two files in it, README and addendum. Its README says Thank you for reading. Let's do that checkout:

$ git checkout aaa1 -- .
[output snipped]
$ ls
README    addendum  hello

(I added the --: it's not actually required here, but it's good practice.) The contents of README are the updated README. The file addendum has also been extracted. The file hello is not removed and remains unchanged from the version found in master. The updated README and hello are staged:

$ git status --short
M  README
A  addendum

but hello is not removed:

$ git ls-files --stage
100644 ac6f2cf1acbe1b6f11c7be2288fbae72b982823c 0   README
100644 7ddf1d71e0209a8512fe4862b4689d6ff542bf99 0   addendum
100644 cc628ccd10742baea8241c5924df992b5c019f71 0   hello

Using git clean, even with -x, will have no effect: nothing needs cleaning; there are no unstaged files (hello is staged, it's just not modified).


You specifically wanted to get the work-tree to match commit aaa1, byte for byte. To do that, you must find files that are in the index now, but were not in aaa1, and remove them.

There is, however, an easier way: just remove everything. Then, use your git checkout aaa1 -- . to extract everything from aaa1. This will fill in the index and work-tree from aaa1: any files that need to be restored to the way they were before removing, are restored (to the way they were in aaa1 which is the same as the way they are in HEAD). Any files that need to be changed to match the way they were in aaa1, are restored (to the way they were in aaa1 which is different).

$ git rm -rf .
rm 'README'
rm 'addendum'
rm 'hello'
$ git checkout aaa1 -- .
$ git ls-files --stage
100644 ac6f2cf1acbe1b6f11c7be2288fbae72b982823c 0   README
100644 7ddf1d71e0209a8512fe4862b4689d6ff542bf99 0   addendum
$ git status --short
M  README
A  addendum
D  hello

You can now commit and you will have a new commit on master that, regardless of what was there before, has exactly the same tree as aaa1.

(Whether this is a good idea is another thing entirely, but it will get you the desired state.)

这篇关于git checkout不会删除应该删除的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆