65.9K
CodeProject 正在变化。 阅读更多。
Home

Git – “skip-worktree”与 Pull 的问题

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2023年7月10日

CPOL

4分钟阅读

viewsIcon

18936

使用 Git “skip-worktree” 选项可能会导致 Git Pull 出现问题。

1. 问题

如果您有一个像 web.config 这样的配置文件,它需要被 Git 跟踪,但您希望忽略本地的更改,这种情况无法通过 .gitignore 解决。我们将展示实现此目标的替代方法。

有关在 Git 中忽略文件的更多方法,请参阅 [1]。

skip-worktree 选项是一个不太为人所知的 Git 选项。此方法旨在应用于您希望跟踪、忽略本地更改的文件。这是 .gitignore 方法的推荐替代方案。

但是,问题在于,skip-worktree 选项仍然需要 Git 对情况进行仔细管理。如果在其他地方修改了原始文件,尝试执行 Git Pull 可能会导致错误,并拒绝 Pull。需要仔细的手动管理/解决情况。

2. 从命令行使用 skip-worktree

以下是您需要的命令

忽略已跟踪文件的本地更改

git update-index --skip-worktree  [<file>...]

重新跟踪本地更改

git update-index --no-skip-worktree [<file>...]

列出所有标记为 skip-worktree 的文件

git ls-files -v | grep ^S

3. “skip-worktree” 选项的问题情况

让我们解释一下问题情况是如何生成的。假设我们有两个用户,每个用户都有自己的仓库。让我们关注一个文件 config.txt。最初,所有仓库的文件版本都相同。

然后,User1 在他的系统上决定修改 config.txt,但不想提交更改,因此他使用 skip-worktree 选项对其进行标记。

然后,User2 在他的系统上作为其正常工作的一部分修改了 config.txt

然后,User2 提交了他的工作并将更改推送到远程仓库。

现在,当 User1 想要从远程仓库 Pull 时,我们就遇到了问题。

问题在于 Pull 被拒绝并出现错误。文件 config.txt 无法修改。更糟糕的是,我们现在有两个版本的 config.txt 文件,版本 A1A2

Pull 生成的错误将类似于

error:
Your local changes to the following files would be overwritten by merge:
                Folder1/config.txt
Please commit your changes or stash them before you merge.
Aborting

4. 理解问题

问题在于,“本地仓库 1”上的 config.txt 版本为 A1,该文件已被修改并通过 skip-worktree 标志进行保护。Git 无法触及该文件。User1 希望拥有 config.txt 的本地版本 A1,但现在全局版本已更改为 A2

如果用户仅解除 skip-worktree 标志(git update-index --no-skip-worktree config.txt),文件 config.txt Ver A1 将仅显示为“本地仓库 1”中的 UNSTAGEDUNCOMMITTED

User1 现在肯定需要合并版本 A1A2,问题在于他是否希望将他的版本 A1 的更改提交到“远程仓库”。

5. 问题解决

5.1. 变体 1:提交本地更改

如果 User1 决定他实际上想将他的更改 ver A1 提交到“远程仓库”,他将解除 skip-worktree 标志。由于文件 config.txt ver A1 未提交,Git Pull 仍然无法工作。User1 决定将文件 config.txt 提交到“本地仓库 1”。User1 再次执行 Pull,然后自动或手动将 config.txt 合并到版本 A12。然后,他将文件 A12 提交到“本地仓库 1”。然后 Push 到“远程仓库”。

现在“远程仓库”拥有版本 A12,而 User1 在“本地仓库 1”中也拥有版本 A12

User1 的步骤是

  1. 在“本地仓库 1”中解除 config.txt ver A1skip-worktree 标志
    (git update-index --no-skip-worktree config.txt)
  2. 将文件 config.txt ver A1 提交到“本地仓库 1”
  3. 拉取 (Pull)
  4. 解决文件合并(得到文件 config.txt ver A12
  5. 将文件 config.txt ver A12 Push 到“远程仓库”

5.2. 变体 2:Stash 本地更改

如果 User1 决定他不想将他的更改提交到“远程仓库”,他将解除 skip-worktree 标志。由于文件 config.txt ver A1 未提交,Git Pull 仍然无法工作。User1 决定 stash 文件 config.txtUser1 再次执行 Pull 并将文件 config.txt ver A2 提取到“本地仓库 1”。然后 User1 将文件从 stash 应用到“本地仓库 1”。Git 将执行自动或手动合并。User1 手动将新文件合并到版本 A12。然后,User1skip-worktree 标志应用于文件 A12

现在“远程仓库”拥有版本 A2,而 User1 在“本地仓库 1”中拥有版本 A12

User1 的步骤是

  1. 在“本地仓库 1”中解除 config.txt ver A1skip-worktree 标志
    (git update-index --no-skip-worktree config.txt)
  2. Stash 文件 config.txt ver A1
  3. 拉取 (Pull)
  4. 将 stash 应用到“本地仓库 1”
  5. 解决文件合并(得到文件 config.txt ver A12
  6. 在“本地仓库 1”中为 config.txt ver A12 设置 skip-worktree 标志
    (git update-index --skip-worktree config.txt)

6. 结论

Git 选项 skip-worktree 是处理诸如 web.config 等配置文件需要本地修改的情况的推荐方法。但是,有时情况会变得相当复杂,就像上面的问题一样,当同一个文件在其他地方被修改,然后 Git Pull 就无法工作时。

Git 没有什么是一帆风顺的。我使用流行的 Git GUI SourceTree,但即便如此,如果没有对您所做的事情有很好的理解,工具本身也无法解决问题。

7. 参考文献

8. 历史

  • 2023年7月10日:初始版本
© . All rights reserved.