git checkout不会删除应该删除的文件

时间:2016-05-13 04:10:42

标签: git git-checkout

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

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

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

但此时aaa1之后添加的一些文件仍在工作副本中。什么是checkout命令来获取工作副本数据返回aaa1处的状态?

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

5 个答案:

答案 0 :(得分:8)

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

即使使用git clean,使用-x也无效:无需清理;没有未暂存的文件(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具有完全相同的树。

(这是否是好主意完全是另一回事,但它会让你达到理想状态。)

答案 1 :(得分:3)

您想将您的回购卷回滚到该状态吗?或者你只是希望你的本地回购看起来像那样?

请参阅https://git-scm.com/docs/git-reset了解git reset。

案例1: 如果你这样做

git reset --hard [commit hash]

它将使您的本地代码和本地历史记录与该提交时一样。但是如果你想把它推给拥有新历史的其他人,它就会失败。

案例2:如果你这样做

git reset --soft [commit hash]

它会使您的本地文件更改为当时的文件,但保留您的历史记录等。

我找到了答案here。 您还可以查看相关答案here

答案 2 :(得分:0)

Git checkout will not remove files added since a previous commit。要做到这一点,我需要git revert

但是我发现git checkout thehash .更容易使用,并且从那个散列开始就不难看出添加了哪些文件:

git diff --name-status HEAD thehash

答案 3 :(得分:0)

git stash 可能是清理工作树的最快方法。 然后 git checkout -b $ newbranch $ commit-sha1-you-want 创建一个你要使用的分支。 完成所有工作后, git stash pop 恢复工作树。

答案 4 :(得分:0)

我发现这个命令将索引和工作副本更新为我想要的提交,在这种情况下由变量 treeish 给出:

# use with care: destroys any uncommitted changes
git read-tree "$treeish" --reset -u

要在不更新索引的情况下更新工作副本,您可以这样做:

index_bak=$(git write-tree)
git read-tree "$treeish" --reset -u
git read-tree "$index_bak" --reset