Git 使用已更改的 --skip-worktree 文件切换分支

Git switch branches with changed --skip-worktree file

我有一个文件 abc.log(出于某种原因)在 git 中进行了跟踪,但我(可能是愚蠢地)将其设置为 --skip-worktree,因此对其进行的更改不会显示在我对存储库的提交中。我想换分店:

~ % git checkout master                                                
error: Your local changes to the following files would be overwritten by checkout:
    abc.log
Please commit your changes or stash them before you switch branches.
Aborting

然后我尝试刷新索引并强制结帐:

~ % git update-index --really-refresh 
~ % git checkout master -f
error: Entry 'abc.log' not uptodate. Cannot merge.

然而,abc.log在本地没有任何变化:

~ % git status            
On branch xyz
Your branch is ahead of 'origin/xyz' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

Undo git update-index --assume-unchanged <file>之后,我尝试再次将其设置为no-skip-worktree。

~ % git update-index --no-skip-worktree --no-assume-unchanged abc.log
fatal: Unable to mark file dump.rbd

按照 之类的建议,我看到它被 git 跟踪,目前设置为跳过工作树

~ % git ls-files -v | grep "S "                                        
S abc.log

然而,仅仅寻找它并没有显示出来

~ % git ls-files --error-unmatch abc.log                           
error: pathspec 'abc.log' did not match any file(s) known to git
Did you forget to 'git add'?

而且我无法添加如下

~ % git add dump.rbd
fatal: pathspec 'abc.log' did not match any files

您已经找到了 Git FAQ states there's no way to ignore changes to tracked files 的原因。来自常见问题解答:

Git doesn’t provide a way to do this. The reason is that if Git needs to overwrite this file, such as during a checkout, it doesn’t know whether the changes to the file are precious and should be kept, or whether they are irrelevant and can safely be destroyed. Therefore, it has to take the safe route and always preserve them.

It’s tempting to try to use certain features of git update-index, namely the assume-unchanged and skip-worktree bits, but these don’t work properly for this purpose and shouldn’t be used this way.

这根本行不通,也没有办法让它发挥作用。你只需要不那样做。由于该文件看起来像一个日志文件,它可能根本不应该签入,这将解决您的问题。您可以使用 git rm.

删除它

是这种情况的正确选择,但更一般地说,它 可以暂时使用 --skip-worktree 进行一些未提交的更改.当你运行陷入这个问题时,使用的技巧是:

  1. 清除--skip-worktree标志(使用git update-index --no-skip-worktree <em>path</em>.)
  2. 添加并提交更改,作为对一个文件(或一组文件)的更改。给它一个好的提交消息,这样你就可以找到这个提交很容易,包括在它变基之后。
  3. 获取上游提交。
  4. 根据需要变基或合并。
  5. 使用 git rebase -i 将步骤 2 中的提交“移动”为分支上的单独最终提交。确保一切仍然有效,并且您仍然希望将其作为设置为 --skip-worktree 的未提交更改进行处理,即您不希望 committed 更改此文件(或这些文件,复数)。如果您确实想要提交更改,请根据需要进行这些更改、提交和重复,以便您要携带的“额外”更改仍然是最终提交。
  6. 使用 git reset(默认为 --mixed)删除最终提交,其中包含您希望作为未提交更改保留的更改。
  7. 使用git update-index再次设置--skip-worktree标志。

这个简单的 7 步过程可让您轻松地进行更改。如果多个文件受到影响,您可能希望编写一个小工具来让您适当地添加和清除 --skip-worktree 标志。 (I have one that lets you view and remove the flags easily,但不是一个可以让您将它们添加回去的程序——这只是输入 for i in <list>; do git update-index --skip-worktree $i; done 的问题,而我在执行此操作时不想在自动化方面走那么远。 )