I'm having trouble with a basic git pull. When I check git status, the working tree is clean. But when I try to pull or fetch and merge, git says local changes will be overwritten and gives me a list of files. I've tried git reset --hard HEAD
and then merging, but same problem. I also tried git stash
but still nothing.
All the files that git complains about are in the obj/ directory, which I have in my gitIgnore, so I'm not completely sure why git is worrying about these files to begin with. *However, I have had issues with git tracking files that I previously hadn't included in my gitignore. I tried to untrack problem folders and files with git update-index --skip-worktree
, but I wouldn't be surprised if that's still part of my problem.
Any advice on the best next move? My objective is to pull the remote commit and I don't care about the local files git is referring to.
git merge error even after clean worktree
CodePudding user response:
You can see for yourself whether the remote has those files with git ls-tree origin/main
Your git stash
didn't save anything because you're (probably) ignoring those files with a local .gitignore
. Try again with git stash --include-untracked
.
once the local files are stashed, run git pull
again to try to merge your local with the remote.
CodePudding user response:
I tried to untrack problem folders and files with
git update-index --skip-worktree
, but I wouldn't be surprised if that's still part of my problem.
Yes, it is.
There are two flags that people attempt to use here, --assume-unchanged
and --skip-worktree
. Neither one works, except sometimes—okay, extremely often—by accident, as it were. Unfortunately, the fact that it works "by accident" so often makes people believe that it's supposed to work. The fact that it comes up so often implies that Git probably ought to have some way to make this work, but Git doesn't.1
What you did with --skip-worktree
was to make Git quietly ignore the fact that your obj/
files are updated vs their obj/
files. This doesn't work right: not exactly. What it does is set things up so that new commits that you make, use the old obj/
files instead of your updated obj/
files. The correct solution probably would have been to remove the obj/
files from all future commits, but this is somewhat disruptive and requires that everyone working with the repository coördinate (though not all at once). (Ideally, one might remove the obj/
files from past commits as well, but this is much more disruptive and requires a great deal more coördination. The remove-and-proceed method can be done incrementally so it's much more manageable.)
To make things work now, you must unset the --skip-worktree
bit that you set for each file that you set it for. You then have to figure out what to do with each file: i.e., for all the files that you put off figuring out what to do earlier, you must now figure out what to do.
Probably, the right thing is to remove them, as already noted. However, you may be able to go back to your "defer working on that" by:
- moving the correct-for-you files out of the way, so that they're not in the repository at all;
- using
git restore
(orgit checkout
if you have an old Git version) to put back the wrong files that are in the repository; - go ahead and merge, which will now work;
- remove the wrong-for-you files by putting the moved-aside files back; and
- set the
--skip-worktree
bit again.
This will put you back in the position you had before, with the "solve problem correctly" part deferred, exactly as you have been working.
1As I like to say, Git is a tool, not a solution. I have a friend whose armed forces instructor used to hammer on this point, especially with things like GPS navigation. If the GPS says turn on this road, and there's no actual road there, don't assume that you should turn there. This happened to me once in Australia. I'm not sure if there was a plan to have a road there in the future, or if there had been a road there in the past, but there wasn't a road there then.