How to make git merge handle uncommitted changes to my working tree?

GitGit MergeGit Stash

Git Problem Overview


A co-worker and I are both working on the master branch at the moment. I have some code in my working tree that I don't want to commit (debugging statements and the like). Now if he commits changes to some of those same files, I can't merge them:

$ git merge origin/master
Updating 1b8c5c6..eb44c23
error: Entry 'blah.java' not uptodate. Cannot merge.

Coming from a subversion background, I'm used to having my working tree automatically merged when I pull changes from the repository and if there are conflicts, I resolve them manually.

The quickest way I have found to do this in git is:

$ git stash
$ git merge origin/master
$ git stash pop

Essentially, removing my uncommitted changes, doing the merge and then re-applying the changes. How can I tell merge to automatically merge my working tree with the changes I'm trying to pull in?

Git Solutions


Solution 1 - Git

Forget everything you ever learned from subversion.

Always commit before introducing external changes.

Imagine you had a mostly-working tree -- maybe not perfect, but you're making some progress. Then you go to do a merge and the code you're bringing in just wreaked havoc (was buggy itself, too many conflicts to deal with, etc...). Wouldn't it be nice if you could just undo that?

If you commit, you can. If you don't, you're just going to suffer.

Remember: What you commit doesn't have to be what you push, but what you don't commit you can easily lose.

Just do the safe and easy thing and commit early and commit often.

Solution 2 - Git

As far as I can tell, the best you can do is what you already have with git stash. I too find it strange that merge wants to deal only with clean trees.

Solution 3 - Git

  • If local work is uncommitted
    • And you've introduced completely new files that don’t exist in the remote branch:
    • Or the files affected by your local work have ZERO overlap with the files affected by the changes you need to pull from the remote:
      • You're in luck: git pull will "just work"
    • Otherwise:
      • If your local changes have NO overlap with changes you are pulling:
        • git stash will work:
          • git stash save
          • git pull
          • git stash pop
      • If your local changes have SOME overlap with changes you are pulling:
        • git stash will require manual conflict resolution:
          • git stash save
          • git pull
          • git stash pop
          • resolve merge conflicts
          • git reset
          • git stash drop
  • If local work is committed
    • And the files affected by your local work have ZERO overlap with the files affected by
      • You're in luck: git pull will "just work"
      • However: git pull --rebase will "work even better" because of a cleaner history
      • there is no merge commit; your changes will be committed after upstream changes
    • Otherwise:
      • git pull will require manual conflict resolution:
        • git pull
        • resolve merge conflicts
        • git add FILE for each conflicting FILE
        • git commit
      • git pull --rebase could still "work even better" because of a cleaner history
        • however, resolving merge conflicts could be much harder

For a detailed explanation, please see: https://happygitwithr.com/pull-tricky.html

Solution 4 - Git

You cannot tell git merge to merge changes on files that have changes with respect to your local repository. This protects you from losing your changes on those times when a merge goes badly.

With the CVS and SVN approach to merging, if you did not manually copy your files before the update and it scrambled them on merge, you have to manually re-edit to get back to a good state.

If you either commit your changes or stash them before doing a merge, everything is reversible. If the merge does not go well you can try several ways of making it work out and go with the one that works best.

If you do commit experimental or debug changes, you might use git rebase to move them after the commits you get via git merge to make it easier to get rid of them or to avoid pushing them to a repository accidentally.

Note that using git rebase on a branch you have pushed to a shared repository will cause grief for everyone who is pulling from that repository.

I prefer to use git stash in these cases, but I only use it if the merge changes files that I have edited and not committed.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJeremy HuiskampView Question on Stackoverflow
Solution 1 - GitDustinView Answer on Stackoverflow
Solution 2 - GitNorman RamseyView Answer on Stackoverflow
Solution 3 - GitLeonardo GonzalezView Answer on Stackoverflow
Solution 4 - GitJamey HicksView Answer on Stackoverflow