Git说有变化,但没有

时间:2018-05-14 16:57:45

标签: git

首先,我无法放弃对文件的更改,我使用git reset --hard,没有错误,但更改仍然存在。我尝试了其他StackOverflow文章中的几条建议。

git rm .gitattributes
git add -A
git reset --hard
git rm --cached [fileName]

我甚至吹走了我的仓库,并立即克隆了新的仓库,它有相同的修改文件。如果我手动更改文件(使用编辑器删除GIT的不同之处),我现在可以在修改后的列表中看到它两次(例如,当我运行git status时,我看到同样的文件路径在非分段文件下列出两次)。最后找到一个实际重置文件并从修改后的列表中删除它的文件。

git ls-files -m | xargs -i git update-index --assume-unchanged "{}"

现在,我尝试切换分支,它表示更改将被覆盖,我必须提交或存储我的更改,但是,当我运行git stash时,它告诉我没有更改。我已经尝试了几个建议,包括尝试update line endings,没有什么可以让我结帐分支。分支中确实有一个“/”,这可能导致问题吗?

  

C:\ git \ azureWebApps \ CRM-WebAPI(qa - > origin)λgitstatus
  在分支qa
  你的分支是最新的'origin / qa'。

     

无需承诺,工作树干净

     

C:\ git \ azureWebApps \ CRM-WebAPI(qa - > origin)λgitdiff

     

C:\ git \ azureWebApps \ CRM-WebAPI(qa - > origin)λgitcheckout feature / PEN-146-CreateUpdatePerson
  错误:对以下文件的本地更改将被>覆盖。查看:           CRM-RESTAPI / web.config中
  请在切换分支之前提交更改或存储更改   中止

     

C:\ git \ azureWebApps \ RM-WebAPI(qa - > origin)λgitstash
  没有保存的本地更改

2 个答案:

答案 0 :(得分:4)

[注意:这毕竟是一个文件名案例问题;看"编辑"下方。]

  

...立即克隆了新鲜的repo,它具有相同的修改文件

这意味着正在进行两件事之一:

  • 文件 更改,或
  • Git想知道哪个文件与您机器上的实际情况不符。
  

如果我手动更改文件,我现在可以在修改后的列表中看到它两次。

这没什么意义。如果你包含了你的意思的剪切和粘贴,这将有所帮助。

每次评论

[编辑:,这就像 - 我会使用实际文字,但我必须重新创建它,因为我自己没有问题 - 以下内容:

(boilerplate snipped)
    modified:   CRM-RestAPI/Web.config
    modified:   CRM-RestAPI/web.config

虽然 Git 将这些文件视为两个单独的文件(因为它们将位于区分大小写的文件系统上),但如果您的操作系统执行大小写 - 折叠(默认情况下Windows或MacOS执行此操作),只有一个文件,以大写或小写W命名,而不是两者都有,两种情况都有两个字母。这是我在下面描述的一般问题的一个具体示例,其中Git将文件名存储为几乎任意的字节字符串,但并非所有操作系统都这样做。]

您需要找到并解决问题的背景

由于目前还不清楚问题到底是什么,因此无法解决问题。它可能是行结束问题,也可能是其他问题。您需要以下信息。

每个文件都有三个版本

在大多数情况下 - 它总是包含任何新的克隆 - 您可以看到的每个文件都存在于三个版本中。所有三个应该通常是相同的,但它们可以不同(有意或无意)。

在任何情况下,您都有当前提交,您可以通过以下方式找到其哈希ID:

git rev-parse HEAD

当您检查不同的提交或进行新的提交时,当前提交的哈希ID会发生变化,但总是某些当前提交(有一个例外情况不会发生)这里)。

如果您git checkout特定提交,则每个提交都会列出一堆应该检出的文件。如果需要,您可以使用以下方法查看这些文件:

git ls-tree -r <commit-hash>

向您展示了与该提交相关的每个文件的详细信息。

每个提交都是只读的 - 在此哈希ID下,存储在此提交中的文件永久存储在 1 中,并且它们永远不会更改。

每个文件的第二个副本都保存在Git的索引中。这是你用git update-index --assume-unchanged操纵的东西。索引是Git用于许多事情的中心数据结构,但它最好被描述为,你(和Git)构建你将要做的下一个提交。因此,索引通常从完全匹配当前提交开始。当前提交中的每个文件在索引中都是 ,采用与Git相同的特殊Git压缩格式。 (从技术上讲,索引只是共享提交的文件副本。)索引副本和提交副本之间的重要区别在于索引副本可以被覆盖,之后索引是不再共享提交的文件版本。索引副本仍然是特殊的Git压缩格式,但与提交的副本不同,您可以覆盖索引副本。

每个文件的最后一个副本都是您实际使用的文件。此文件在计算机上处​​于正常的日常格式,而不是以特殊的Git格式。因为 是正常形式,所以你的系统所施加的限制,以及我们进入有趣部分的地方。< / p>

1 无论如何,作为提交本身的永久性。如果你让Git忘记了提交,那么文件本身就会消失,除非其他提交(S)正在共享它们。

HEAD,索引和工作树

我们可以通过标记它们来说明这三个副本:

  HEAD        index     work-tree
---------   ---------   ---------
README.md   README.md   README.md
somefile    somefile    somefile

等等。 Git在这些不同版本之间复制文件,除了HEAD(已提交)版本始终是只读的,因此要更改&#34;在已提交的版本中,Git根据目前的中的任何内容构建 new 提交。

git status命令通过首先将每个文件的HEAD版本与每个文件的索引版本进行比较来告诉您这些信息。如果此处的内容不同,git status将打印文件的名称,并告诉您这是一个可以提交的更改。然后,它将每个文件的索引版本与每个文件的工作树版本进行比较。如果这里的内容有所不同,git status会打印文件的名称,并告诉您这是一个尚未进行提交的更改。

git checkout命令将文件从提交复制到索引和工作树,或从索引复制到工作树。 (这些应该是单独的命令 - 并且在某一点上。)git reset命令将文件从提交复制到索引,但不复制到工作树。 git add命令将文件从工作树复制到索引。 git commit命令从索引中的任何内容生成 new 提交,然后排列事物,以便HEAD现在引用新提交。

感兴趣的东西,或者,寻找什么

既然你知道各个部分的内容,那么事情就会出错。

HEAD和索引不需要使用计算机本机名称格式

存储在提交和索引中的文件的名称只是Git中的字节字符串。除了使用斜杠将目录名与子目录和文件分开,以及使用ASCII NUL字节终止这些字节字符串之外,Git通常是#nc;编码agnositc&#34;。这允许Git使用UTF-8来编码文件名,因为UTF-8编码从不将斜杠/(ASCII 0x2f)以外的任何字符编码为字节代码0x2f。如果您使用反斜杠而不是斜杠,那么它也允许在内部使用正斜杠,或者Git会根据需要转换斜杠,以便这一切都能正常工作。

这也意味着 Git 的文件名区分大小写:文件README与文件readme完全不同,不同于两个不同的文件ReadmeReadMe。目录名称也是如此。

与此同时,您自己的计算机可能在敏感文件系统中有一个案例:此处只有一个文件,其名称取决于您选择的第一个文件。如果您有一个名为ReadMe的文件并且您打开README,则会获得ReadMe,而不是名为README的新文件。 (默认情况下,Windows和MacOS就是这种情况。)

同样,如果您的计算机规范化名称,例如schön,则此名称有两种不同的UTF-8拼写,Git会将它们视为两个不同的文件名,但是您的计算机将它们视为指一个文件。 (在MacOS上就是这种情况;我不确定Windows。)

如果这是问题,那就相当普遍且难以处理。最好的办法是启动Unix或Linux系统,不会进行大小写折叠和规范化,并与存储库一起使用以消除有问题的文件名。然后,您可以检查已修复的任何提交,因为这些提交不再提供使您的操作系统运行的名称。

行尾和其他过滤器

除了文件名之外,你还看到Git可以摆弄行结尾。在Linux或类Unix系统上制作的存储库通常使用仅换行(仅限LF)行结尾,而在Windows系统上编辑的文件可能需要回车换行序列(CR-LF或CRLF结尾)。为了实现跨系统工作,Git提供了一些能力,但不是要求,做一些偷偷摸摸的行结束变化。

一般来说,这种方式的工作方式是Git将某些文件称为 clean ,而将某些文件称为污迹。存储在提交和索引中的内容(即,压缩的仅Git格式)始终假定为 clean 。每当Git将文件从索引复制到工作树时,它涂抹文件,每当它将工作树中的同一文件复制回索引时,清理文件。

如果启用CRLF行结尾,则涂抹过程包括将LF-only更改为CRLF,清理过程包括将CRLF更改为仅LF。 2 这意味着只要所有文件都在存储库非常干净,它们在您的Windows系统上被适当污迹化,并且在git add清除文件之前git commit重新清理它们。

但是 - 这是关键点 - 所有这一过程都是可选的。 Linux用户不会为任何一个付费,因为他们关闭了所有这些,而Linux然后,Git存储库将工作树中的任何内容存储到索引版本中,即使工作树文件具有CRLF行结尾。然后可以提交这些,以便提交&#39;内容包括CRLF结尾。

如果将此类文件解压缩到Windows计算机上并启用了CRLF清除,则index-&gt;工作树转换将单独保留CRLF。但是现在所有的工作树文件都将其CRLF改为LF-only,因此它们不再匹配!他们都立即改变了(但尚未准备好承诺)。

这种情况也是非常棘手的,因为Git通过各种方式尝试了解工作树文件何时被弄脏或清理,而不会在所有污迹和清理过程中运行它们。 (它有点慢 - 非常慢,在某些情况下 - 所以这通常很重要。)但这意味着&#34;改变了&#34;文件有点不可预测,很难诊断。诀窍是检查原始文件内容,如果您再次克隆Linux系统上的存储库,那么这是最简单的,因为在那里,所有行结尾都没有操作。然后,您可以使用行尾结束检查器来查看文件中的内容。

(您可以使用git cat-file -p在其他系统上执行此操作,以提取特定文件,而不会产生任何污迹或其他过滤器或文本转换,并使用行结束检测器检查生成的字节流。如何操作后者在Windows上,我不知道 - 我通常会避免使用Windows系统.MacOS有cat -vhexdump。)

2 我们说&#34;包括&#34;而不是&#34;由&#34;组成。这里是因为您可以编写自己的涂抹和清洁过滤器,除了 CRLF调整之外,还应用

答案 1 :(得分:0)

我正面临类似的问题-

Shell文件的CRLF行结尾于开发分支,而LR行结尾于功能分支

当我从功能分支切换到开发分支时,我遇到了文件被修改的问题。

以下步骤对我有用-


git ls-files -m | xargs -i git update-index --assume-unchanged "{}"

git reset --hard "LATEST COMMIT ID"

git checkout to feature_branch```

This issue will continue to appear until I merge my branches and have shell script with one line ending LF