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

39,896

Solution 1

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 2

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 3

  • 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

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.

Share:
39,896
Jeremy Huiskamp
Author by

Jeremy Huiskamp

Updated on March 19, 2020

Comments

  • Jeremy Huiskamp
    Jeremy Huiskamp about 4 years

    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?

    • Anonigan
      Anonigan almost 15 years
      What if you have merge conflicts? What if you would have merge conflicst in dirty files (files you modified)? See also "Fun with keeping local changes around" at Junio C Hamano (git maintainer) blog: gitster.livejournal.com/29060.html
    • Jeremy Huiskamp
      Jeremy Huiskamp almost 15 years
      Thanks for the link. Again though, the vast majority of the time, I expect either no conflicts or very minor ones which I don't mind fixing by hand. I run the same risk of conflict if I commit my dirty files anyway, except then I have to go to the trouble of uncommitting them after.
    • leo9r
      leo9r about 8 years
    • Keith Mason
      Keith Mason about 7 years
      The problem with using stash is that MERGE_HEAD gets cleared, which causes only the last merge to be recorded. To let the merge revision keep all the parents, you have to set aside a copy of .git/MERGE_HEAD before running git stash. Then you have to combine all of the MERGE_HEADs together (one SHA per line) before the final commit.
    • Walter Nissen
      Walter Nissen over 5 years
      You might add a git fetch origin master before the merge.
  • Jeremy Huiskamp
    Jeremy Huiskamp almost 15 years
    So I commit my debugging statements and then merge. Then I do some real changes that I want to push. How do I get my debugging statements out, now that stuff I want to commit is dependent on that commit?
  • 1800 INFORMATION
    1800 INFORMATION almost 15 years
    You can always revert a previous commit using the "revert" command
  • Jeremy Huiskamp
    Jeremy Huiskamp almost 15 years
    I will consider this strategy for when our code actually gets crazy enough that I have to worry about undoing it. However, for now, I believe the stash version is still reversible. I can re-stash, kill the merge commit and pop the stash again on whatever other commit I want. I don't mind forgetting what I've learned about subversion, but it blows when it does something much better than git, particularly when git is supposed to be the one that's so good at merging.
  • Jeremy Huiskamp
    Jeremy Huiskamp almost 15 years
    I shall put this in my .bashrc: gm() { git stash; git merge $@; git stash pop } And then wait to see how long it takes to bite me in the ass somehow.
  • araqnid
    araqnid almost 15 years
    You could use "rebase -i" to reorder the commits and move the introduction of the debugging statements to the end.
  • reto
    reto over 14 years
    @jeremy: you will end up applying a very very old stash one day :). happened to me :).
  • Casebash
    Casebash about 12 years
    Stashes can be recovered after popping. I don't think committing incomplete and untested code into the repository is a good idea
  • Casebash
    Casebash about 12 years
    @reto: How would that happen?
  • reto
    reto about 12 years
    Casabash: git stash pop doesn't remove the stash if it wasn't able to apply it without conflicts. Then a some timelater you run the miniscript again when you dont have no local changes. Git stash is a noop, then git merge, and after that you pop the old stash again...
  • JohnPristine
    JohnPristine about 11 years
    What are you talking about? SVN backsup your files before merging. Git is the C++ of version control. It takes proud in being overly complex and complicated.
  • andyroschy
    andyroschy almost 10 years
    You could add a git stash clear statement before the git stash, that way you make sure the stash is clean before applying it. You should make sure there's nothing of value in the stash first though.
  • Jamey Hicks
    Jamey Hicks almost 9 years
    I guess my knowledge of SVN is out of date. Git also evolves to become more useful over time. I just saw a talk on Gitless yesterday, which acts on git repositories but is much easier to use when you have uncommitted changes and want to merge or change branches.
  • user83358
    user83358 about 8 years
    I looked up this question because I had the same situation, and I knew there was 0 chance of a conflict (1 line changed in the remote, 4 lines changed in the working copy, completely separate code areas). With all the ways git will allow you to mess up your working copy and your commits, it seems strange that this is one of the few that isn't allowed :)
  • AlbatrossCafe
    AlbatrossCafe almost 8 years
    I had NO CHANGES in my working directory. Nothing was modified. I still couldn't merge into my branch. I had to do git stash in the command prompt. Even though it said "no local changes - nothing to stash" for some reason afterwards I was able to now do git merge. Makes no sense
  • MSalters
    MSalters over 6 years
    Debug commits should be squashed with the commits that remove them.
  • 1valdis
    1valdis about 5 years
    Nicely structured answer.