Git - Problem with “skip-worktree” and Pull

Abstract: Using Git “skip-worktree” option is recommended approach when you want files TRACKED by Git but want LOCAL CHANGES IGNORED, and it is more appropriate than .gitignore. However, if files are modified by other users, Git Pull can be problematic and requires elaborate handling.

Problem

If you have a config file like web.config that needs to be TRACKED by Git but want LOCAL CHANGES IGNORED, that situation cannot be solved with .gitignore. We show alternative ways to achieve that.

For more discussion on methods to ignore files in Git, see [1].

The skip-worktree option is a less-known Git option. This method is planned to be applied to files that you want TRACKED, LOCAL CHANGES IGNORED. This is recommended alternative to the .gitignore method.

But, the problem is the option “skip-worktree” still requires careful management of the situation in Git. If the original file is modified elsewhere, an attempt to execute “Git Pull” can lead to an error and to the Pull being refused. Careful manual management/resolution of the situation is needed.

Usage of skip-worktree from the command line

Here are the commands you will need for this method:

To ignore local changes to tracked files:
git update-index --skip-worktree  [<file>...]

To track local changes again:
git update-index --no-skip-worktree [<file>...]

To list all files marked with skip-worktree:
git ls-files -v | grep ^S

The problematic situation with the option “skip-worktree”

Let us explain how a problematic situation is generated. Let us assume we have 2 users, each with its own repository. Let us focus on some file config.txt. Initially, all repos have the same version of the file.

Git – Problem with “skip-worktree” and Pull

Then, User1 on his system decides to modify the config.txt but does not want changes committed, so it marks it with the option “skip-worktree”.

Git – Problem with “skip-worktree” and Pull

Then, User2 on his system modifies config.txt as a regular part of his work.

Git – Problem with “skip-worktree” and Pull

Then, User2 commits his work and Pushes changes to the Remote Repo.

Git – Problem with “skip-worktree” and Pull

Now, we have a problem when User1 wants to Pull from Remote Repo.

Git – Problem with “skip-worktree” and Pull

The problem is that Pull is refused with error. File config.txt can not be modified. Even worse, we have now 2 versions of file config.txt, version A1 and A2.

The error generated by Pull will be similar to:

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 Understanding the problem

The problem is that on “Repo Local 1” we have config.txt version A1, which is modified and protected by the flag “skip-worktree”. Git can not touch that file. User1 wanted to have the local version A1 of config.txt, but now the global version has changed to A2.

If the user just releases a flag “skip-worktree” (git update-index --no-skip-worktree config.txt), file config.txt Ver A1 will just appear UNSTAGED and UNCOMMITTED in “Repo Local 1”.

User1 now definitely needs to merge versions A1 and A2, just question is if he wants to commit changes from his version A1 to the “Remote Repo”.

Problem resolution


5.1 Variant 1: Commit local changes

If User1 decides he actually wants to commit his changes ver A1 to “Remote Repo”, he releases the flag “skip-worktree”. Since file config.txt ver A1 is not committed, Git Pull will still not work. User1 decides to commit the file config.txt to “Repo Local 1”. User1 does Pull again, then automatically or manually merges config.txt into version A12. Then it commits file A12 into “Repo Local 1”. And then does Push to the “Remote Repo”.

Now “Remote Repo” has version A12, and User1 also in “Repo Local 1” has version A12.

Git – Problem with “skip-worktree” and Pull

Steps for User1 are:

  1. Release flag “skip-worktree” on config.txt ver A1 in “Repo Local 1”

    (git update-index --no-skip-worktree config.txt)

  2. Commit file config.txt ver A1 to “Repo Local 1”
  3. Pull
  4. Resolve file merge (resulting in file config.txt ver A12)
  5. Push (file config.txt ver A12 to “Remote Repo”)

5.2 Variant 2: Stash local changes

If User1 decides he does not want to commit his changes to “Remote Repo”, he releases the flag “skip-worktree”. Since file config.txt ver A1 is not committed, Git Pull will still not work. User1 decides to stash the file config.txt. User1 pulls again and enters the “Repo Local 1” file config.txt ver A2. Then User1 applies the file from stash to “Local Repo 1”. Git will do an automatic or manual merge. User1 manually merges the new file into version A12. Then, User1 applies flag “skip-worktree” to file A12.

Now “Remote Repo” has version A2, and User1 in “Repo Local 1” has version A12.

Git – Problem with “skip-worktree” and Pull

Steps for User1 are:

  1. Release flag “skip-worktree” on config.txt ver A1 in “Repo Local 1”

    (git update-index --no-skip-worktree config.txt)

  2. Stash file config.txt ver A1
  3. Pull
  4. Apply stash to “Repo Local 1”
  5. Resolve file merge (resulting in file config.txt ver A12)
  6. Set flag “skip-worktree” on config.txt ver A12 in “Repo Local 1”

    (git update-index --skip-worktree config.txt)

Conclusion

The Git option “skip-worktree” is recommended way of dealing with situations when you have config files like web.config that you need to locally change. But, sometimes, situations can become quite complicated, like in the above problem when the same file gets modified elsewhere and then the Git Pull is not working.

Nothing is easy with Git. I use the popular Git GUI SourceTree, but still, without a good understanding of what are you doing, the tool itself will not solve the problem.

References

  1. https://www.codeproject.com/Articles/5363864/Git-4-Ways-to-Ignore-Files
  2. https://www.codeproject.com/Articles/5363987/Git-SourceTree-Custom-Actions-for-skip-worktree-Op
  3. https://stackoverflow.com/questions/35690736/handling-changes-to-files-with-skip-worktree-from-another-branch


Similar Articles