git checkout错误,即使git status报告工作树是干净的

时间:2018-11-08 18:34:39

标签: git macos github git-checkout

我在本地my-feature分支机构中

git status报告nothing to commit, working tree clean

我想切换到开发分支并在那里做git fetchgit merge(我更喜欢git pull

但是,这样做会在下面产生错误

我首先在这里检查状态,结果表明一切都很好

mymbp:MyProj username$ git status
On branch my-feature
nothing to commit, working tree clean

下一步,我尝试签出我的开发分支,这是一个现有的本地分支

On branch my-feature
nothing to commit, working tree clean
mymbp:MyProj username$ git checkout develop
error: Your local changes to the following files would be overwritten by checkout:
    MyProj.sln
Please commit your changes or stash them before you switch branches.
Aborting

它抱怨myProj.sln已更改,即使git status说什么都没有改变。

再次发出git status,确认没有任何变化

mymbp:MyProj username$ git status
On branch my-feature
nothing to commit, working tree clean

更新1

执行git ls-files --stage --debug MyProj.sln如下所示,但我看不到任何4000或8000(--skip-worktree--assume-unchanged标志):

mymbp:MyProj username$ git ls-files --stage --debug MyProj.sln
100644 40c3593ed572beb2139c189455274f8900a1340c 0   MyProj.sln
  ctime: 1541703970:521058155
  mtime: 1541637062:121492660
  dev: 16777220 ino: 8470003
  uid: 501  gid: 20
  size: 55684   flags: 0
mymbp:MyProj username$ 

发出git show develop:MyProj.sln会向我显示解决方案中的项目文件及其GUID的数量,用于解决方案前后的Global部分,但是输出很长,仅显示Release,Debug配置和一些GUIDS。尚不确定该怎么办。

更新2

因此,它的接缝好像MyProj.sln文件在工作树中,而不在索引和提交(HEAD)中。根据@torek的解释,发出git add MyProj.sln应该将这个文件添加到索引中,但这是不正确的,因为没有添加任何内容,并且在执行git add之前和执行之后git status均不返回任何内容。同时git checkout仍然抱怨MyProj.sln已更改。 git diff也什么都不返回

更新3

我还发现有人建议发出这两个命令以获取提交HEAD的哈希值,然后查看其中的更改。我看到很多文件重复,有些则没有。那些似乎不是我在当前功能分支中添加的文件。那些重复的文件似乎是来自远程的文件

mymbp:MyProj username$ git rev-parse HEAD
1ca8d8a7c5eff0f2a03eb185f1b25aff27c1d2fd
mymbp:MyProj username$ git ls-tree -r 1ca8d8a7c5eff0f2a03eb185f1b25aff27c1d2fd

这是它的输出

enter image description here

更新4

我的配置是:

mymbp:MyProj username$ git config --list
credential.helper=osxkeychain
core.excludesfile=/Users/username/.gitignore_global
core.autocrlf=input
difftool.sourcetree.cmd=opendiff "$LOCAL" "$REMOTE"
difftool.sourcetree.path=
mergetool.sourcetree.cmd=/Applications/Sourcetree.app/Contents/Resources/opendiff-w.sh "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"
mergetool.sourcetree.trustexitcode=true
user.name=User Name
user.email=username@somesystems.com
color.ui=true
color.status.changed=blue normal
color.status.untracked=red normal
color.status.added=magenta normal
color.status.updated=green normal
color.status.branch=yellow normal bold
color.status.header=white normal bold
commit.template=/Users/username/.stCommitMsg
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/SomeSystems/MyProj.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.develop.remote=origin
branch.develop.merge=refs/heads/develop
branch.feat-1.remote=origin
branch.feat-1.merge=refs/heads/feat/feat-1
branch.1234-refactoring.remote=origin
branch.1234-refactoring.merge=refs/heads/1234-refactoring
mymbp:MyProj username$ 

1 个答案:

答案 0 :(得分:2)

每个更新进行编辑:虽然很难确定是什么(虽然捕获的输出是图像,所以无法检查奇怪的Unicode问题),但这里肯定有些奇怪。在提交树上的git ls-tree -r输出中,任何文件都不应列出两次。我从未从Git中看到过这种行为。大写和小写都有 问题,尤其是在Windows和MacOS上,可能会导致这种行为,但与您在此处显示的内容不符。

下面的原始答案

首先,请注意:您的标签提到了MacOS。 MacOS文件系统默认情况下不区分大小写,因此,如果您有一个名为README.TXT的文件并要求系统查看名为readme.txt的文件,它将显示为README.TXT。如果您要求系统添加名为readme.txt的新文件,它将代替 overwite 现有的 README.TXT并保留大写名称。因此,请注意文件名仅在以下情况下有所不同:Git提交可能具有myproj.sln文件,它将覆盖您的MyProj.sln文件。


至少有两种可能性,但让我们首先考虑最可能的可能性:

  • 这意味着存在一个不在当前索引和提交中的文件,但在当前工作树中的 名为MyProj.sln。您要求Git对git checkout的提交中的 是同一文件。因此,如果您成功git checkout进行另一次提交,则Git将覆盖工作树文件。 Git警告您,您将丢失该文件的 current 内容。

  • 或者,在当前索引和工作树中有一个 文件,名为MyProj.sln。工作树副本与索引副本不匹配。通常,git status会告诉您文件已被修改,但是您已经设置了两个指示Git的索引标志位之一:不要查找对文件的更改,和/或不要如果您不小心发现了一些变化,请告诉我,只需按原样保留索引副本即可。这两个标志位分别为--assume-unchanged--skip-worktree

在两种情况下,如果您确实成功签出了要Git签出的提交,则将覆盖MyProj.sln的工作树副本。如果可以,请立即继续删除文件,然后git checkout将继续。


要查看情况是什么

git ls-files --stage --debug MyProj.sln

如果没有输出,则文件不在索引中(因此也基于git status输出或缺少输出而不在当前提交中)。反过来,这意味着此刻它只是一个未跟踪的工作树文件。

如果您确实获得了输出,它应该类似于我在另一个文件中得到的输出:

$ git ls-files --stage --debug Makefile
100644 b08d5ea258c69a78745dfa73fe698c11d021858a 0       Makefile
  ctime: <number>:<number>
  mtime: <number>:<number>
  dev: <number>  ino: <number>
  uid: <number>  gid: <number>
  size: <number> flags: <number>

flags: <number>显示了假设不变和跳过工作树的位,尽管不是人类友好的格式:skip-worktree是4000而另一个是8000(如果两者都设置后,您将获得c000)。设置skip-worktree位,我实际上得到:

size: 96311   flags: 40004000

在设置假定不变的位时会得到:

size: 96311   flags: 8000

您要切换到的提交(develop的提示)具有文件的提交版本,您可以使用以下命令查看该文件的提交版本(没有覆盖当前副本):

git show develop:MyProj.sln

请注意,一旦您git checkout develop,该文件将位于所有三个活动位置:当前提交,索引和工作树。如果my-feature的尖端提交没有没有文件,则从develop切换回my-feature将从文件中删除。工作树。记住其中大部分的方法是:

  • 通过索引进行提交。
  • 因此,
  • 提交首先被提取到索引中(然后提取到工作树中)。
  • 索引跟踪工作树中应提交的内容。索引副本是提交的副本。 git status将索引与工作树进行比较,以告诉您应复制到索引中的内容。
  • 切换提交时,索引中没有但需要基于新提交的工作树文件得到创建; 文件>在索引中,但是需要根据新提交出现在该索引中,并删除
  • 索引中没有
  • 工作树中的文件未被跟踪,并且被单独保留。

在那之后,假设设置不变和跳过工作树位(如果进行了设置)只是对原本基本一致的规则的微小调整。 .gitignore规则也开始变得有意义:.gitignore中列出的文件是git status 不会抱怨未被跟踪的文件。 (但是,一个重要的副作用是,.gitignore使Git可以在某些情况下自由地 clobber 这样的未跟踪文件,这很难记住,也很难解释。)

相关问题