1. 问题
如果你有一个像 web.config 这样的配置文件需要被Git跟踪,但希望忽略本地更改,那么这种情况无法用.gitignore解决。我们展示了实现这一目标的替代方法。
有关在Git中忽略文件的方法的更多讨论,请参阅[1]。
该skip-worktree选项是一个鲜为人知的Git选项。此方法计划应用于要忽略跟踪、本地更改的文件。这是.gitignore方法的推荐替代方法。
但是,问题是,该skip-worktree选项仍然需要仔细管理Git中的情况。如果在其他地方修改了原始文件,则尝试执行Git 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,版本A1和A2。
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. 理解问题
问题是在“Repo Local 1”上,我们有config.txt版本A1,它被修改并受标志skip-worktree保护。Git无法触及该文件。User1想要拥有本地版本A1的config.txt,但现在全局版本已更改为A2。
如果用户只是释放一个标志skip-worktree(git update-index --no-skip-worktree config.txt),文件 config.txt 的版本A1将在“Repo Local 1”中出现UNSTAGED和UNCOMMITTED。
User1现在肯定需要合并版本A1和A2,只是问题是他是否想将他的版本A1的更改提交到“远程存储库”。
5. 问题解决
5.1. 变体1:提交本地更改
如果User1决定他真的想将他的更改版本A1提交到“远程存储库”,他会释放标志skip-worktree。由于文件config.txt版本A1未提交,因此Git Pull仍然无法正常工作。User1决定将文件 config.txt 提交到“Repo Local 1”。 User1再次Pull,然后自动或手动将 config.txt 合并到版本中A12。然后,它将文件A12提交到“Repo Local 1”中。然后对“远程存储库”执行Push操作。
现在“Remote Repo”有版本A12,User1在“Repo Local 1”也有版本A12。
User1步骤如下:
- “Repo Local 1”中config.txt版本A1上释放标志skip-worktree(git update-index --no-skip-worktree config.txt)
- 将文件config.txt版本A1提交到“Repo Local 1”
- Pull
- 解决文件合并问题(导致文件config.txt版本A12)
- Push(文件config.txt版本A12到“远程存储库”)
5.2. 变体2:存储本地更改
如果User1决定不想将更改提交到“远程存储库”,则释放标志skip-worktree。由于文件config.txt版本A1未提交,因此Git Pull仍然无法正常工作。User1决定存储文件 config.txt。User1再次Pull并进入“Repo Local 1”文件config.txt版本A2。然后User1将文件从存储应用到“Local Repo 1”。Git将执行自动或手动合并。User1手动将新文件合并到版本A12中。然后,User1将标志skip-worktree应用于文件 A12。
现在“Remote Repo”有版本A2,而User1在“Repo Local 1”有版本A12。
User1步骤如下:
- “Repo Local 1”中config.txt版本A1上释放标志skip-worktree(git update-index --no-skip-worktree config.txt)
- 存储文件config.txt 版本A1
- Pull
- 将存储应用于“Repo Local 1”
- 解决文件合并问题(导致文件config.txt版本A12)
- 在“Repo Local 1”中的config.txt版本A12上设置标志skip-worktree(git update-index --skip-worktree config.txt )
6. 结论
Git选项skip-worktree是处理需要本地更改的配置文件(如 web.config)的情况的推荐方法。但是,有时情况会变得非常复杂,例如在上述问题中,当同一文件在其他地方被修改时,Git Pull不起作用。
使用Git并不容易。我使用流行的Git GUI SourceTree,但是,如果没有很好地理解您在做什么,该工具本身将无法解决问题。
7. 参考资料
- [1] https://blog.csdn.net/mzl87/article/details/135981192
- [2]https://blog.csdn.net/mzl87/article/details/135981248
- [3] git - Handling changes to files with --skip-worktree from another branch - Stack Overflow
https://www.codeproject.com/Articles/5364391/Git-Problem-with-skip-worktree-and-Pull