git skip-worktree on files with merge conflict

1.2k views Asked by At

I have a configuration file abc.cfg with local changes for my environment. To prevent pushing local configs to the remote, I use git update-index --skip-worktree abc.cfg on the file.

Now the upstream has changed abc.cfg with global updates that I need. So I first did --no-skip-worktree abc.cfg, did git stash on it, pulled the upstream, and proceed with git stash apply on the file.

Now there's merge conflicts on abc.cfg. I tried to resolve it, and do git update-index --skip-worktree abc.cfg again, but this time it says:

fatal: Unable to mark file scripts/app.js

How should I apply back my local changes without including it in the commits?

2

There are 2 answers

0
VonC On

Now there's merge conflicts on abc.cfg.
I tried to resolve it, and do git update-index --skip-worktree abc.cfg again, but...

The is a corner case which could prevent git skip-worktree to work as intended in case of merge conflict.

When the sparse checkout feature is in use, "git cherry-pick" and other mergy operations lost the skip_worktree bit when a path that is excluded from checkout requires content level merge, which is resolved as the same as the HEAD version, without materializing the merge result in the working tree, which made the path appear as deleted.

This has been corrected in Git 2.19 (Q3 2018) by preserving the skip_worktree bit (and not materializing the file in the working tree).

See commit 2b75fb6 (27 Jul 2018) by Elijah Newren (newren).
See commit 92203e6 (27 Jul 2018) by Ben Peart (benpeart).
(Merged by Junio C Hamano -- gitster -- in commit e4095da, 15 Aug 2018)

merge-recursive: preserve skip_worktree bit when necessary

merge-recursive takes any files marked as unmerged by unpack_trees, tries to figure out whether they can be resolved (e.g. using renames or a file-level merge), and then if they can be it will delete the old cache entries and writes new ones.

This means that any ce_flags for those cache entries are essentially cleared when merging.

Unfortunately, if a file was marked as skip_worktree and it needs a file-level merge but the merge results in the same version of the file that was found in HEAD, we skip updating the worktree (because the file was unchanged) but clear the skip_worktree bit (because of the delete-cache-entry-and-write-new-one).

This makes git treat the file as having a local change in the working copy, namely a delete, when it should appear as unchanged despite not being present.
Avoid this problem by copying the skip_worktree flag in this case.

1
Jyoti Prakash On

I think your project is a mobile application project as you have error in scripts/app.js

You are applying stash, still ignoring it and not want to push your local changes, thats fine. There should not be any issue due to this.

Now, the error you got fatal: Unable to mark file scripts/app.js, I guess its due to the changes you pulled from remote. Do this, take a fresh copy of remote at different location and use any compare tool to see what all files are different in two projects specially the app.js file.