2

我在我当地的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,用于前后解决方案的全局部分,但输出很长,仅显示发布、调试配置和一些 GUID。还不知道该怎么办。

更新 2

因此,它看起来好像 MyProj.sln 文件在工作树中,但不在索引和提交(HEAD)中。根据@torek 的解释,发出 git add MyProj.sln 应该将此文件添加到索引中,但事实并非如此,因为没有添加任何内容,并且 git status 在我执行 git add 之前和之后都没有返回任何内容。同时 git checkout 仍然抱怨 MyProj.sln 已更改。git diff 也不返回任何内容

更新 3

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

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

这是它的输出

在此处输入图像描述

更新 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$ 
4

1 回答 1

2

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

原答案如下

首先,快速说明:您的标签提到了 MacOS。MacOS 文件系统默认不区分大小写,因此如果您有一个名为的文件README.TXT并要求系统查看名为 的文件readme.txt,它会向您显示README.TXT. 如果您要求系统添加一个名为它的新文件,readme.txt它将覆盖现有 README.TXT文件并保留大写名称。因此,请注意名称不同的文件,以防万一:Git 提交可能有一个myproj.sln文件会覆盖您的MyProj.sln文件。


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

  • 这意味着有一个文件不在当前索引和提交中,但当前工作树中,名为MyProj.sln. 同样的文件你要求 Git 的提交中git checkout。因此,如果您成功完成其他提交,Git 将覆盖工作树文件。git checkoutGit 警告您将丢失该文件的当前内容。

  • 或者,在当前索引和工作树中有一个文件,名为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>了假设不变和跳过工作树位,虽然不是人类友好的格式:跳过工作树是4000,另一个是8000(如果两者都设置,你会得到c000)。设置跳过工作树位,我实际上得到:

size: 96311   flags: 40004000

虽然设置假设不变的位给了我:

size: 96311   flags: 8000

您要求切换到的提交(的提示develop)具有文件的已提交版本,您可以通过以下方式查看(不覆盖当前副本):

git show develop:MyProj.sln

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

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

在那之后,假设不变和跳过工作树位(如果您设置它们)只是对原本基本上自洽的规则的微小调整。.gitignore规则也开始变得有意义:其中列出的文件是.gitignore不会git status 抱怨未被跟踪的文件。(然而,一个重要的副作用是.gitignore让 Git 在某些情况下可以随意破坏这些未跟踪的文件,这更难记住或解释。)

于 2018-11-08T20:01:38.937 回答