git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: pull into dirty working tree

From
Junio C Hamano <gitster@pobox.com>
Date
Jun 13, 2007, 17:13 UTC
Message-ID
<7vd4zzeq0s.fsf@assigned-by-dhcp.pobox.com>
In-Reply-To
<Pine.LNX.4.64.0706131559210.4059@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 5 quoted lines
> The other thing, if you have to, is to put all dirty changes into the
> index before pull. Something like "git add $(git ls-files --modified)".
> You can even make that a global alias for your users. Although IIRC it
> does not work if the merge changes the same files as your dirty work tree
> touches, but I could very well be wrong there.

I do not think that would change the issue in general, as the index needs to be clean (wrt HEAD) during a conflicting merge.

Incidentally, I was planning to start a "stash dirty state and later reapply on a different commit" soon (if I survive an event planned tomorrow, that is ;-).

When you are in the middle of something (and when you are not in the middle of a merge), you have two states you care about. What is in the index, and what is in the working tree. Conceptually, even though you do _not_ have commits for these two extra states, your "history" would look like this:

                 o <- working tree state = W
                /
               o <- index state = I
              /
      -------o <- HEAD

A dirty merge (whether it is done as "git checkout $another", "git merge $commit", or "git pull $somebodyelse") is to first stash away I and W, perform the merge proper to advance HEAD, and after all that is done, recreate the index and working tree state on top of the updated HEAD, to arrive at this:

                 o  -->  * <- new working tree state = W'
                /       /
               o  -->  * <- new index state = I'
              /       /
      -------o-------* <- merge = new HEAD
    old HEAD ^      /
                   /
      --------o---o <- other history
This can be internally done as four steps:
 * stash the dirty states (save I and W)
   - record I by "git commit" (no parameters to commit the index).
   - record W by "git add . && git commit -a".
   - remember HEAD as $STASH.
 * match the working tree and the index to original HEAD by
   "reset HEAD^ && reset --hard HEAD".  The first --mixed reset
   is to forget about new files added with "git add .", so that
   the second reset will not remove them from the working tree.
 * perform a merge in the resulting clean tree
 * unstash the dirty states
   - I' is the three-way merge between $STASH~1 and the new HEAD
     using $STASH~2 as the common ancestor.
   - W' is the three-way merge between $STASH and I' using
     $STASH~1 as the common ancestor.

Unstashing operation can potentially require two merge conflict resolutions. As we _care_ about distinction between the index state and the working tree state, this is unavoidable.

    Side note: as an implementation, it is a possibility not to
    record I and record only W as the direct child of the HEAD
    when stashing.  Unstashing would update only the working
    tree (i.e. after unstashing, the index and the HEAD exactly
    matches).  But it risks "forgetting" newly added files and I
    would say it is unacceptable for that reason, even if we
    declare that this feature is only for non-git people.

Combined with the potential conflict resolution for the merge proper, you have to resolve up to three merges in a row. One conflict resolution is something even CVS users must accept anyway, so we are talking about up to two _extra_ conflict resolutions here.

Previous: Bill LearNext: Daniel Barkalow
Message 21 of 35 in “pull into dirty working tree”
  1. Bill LearJun 13, 2007
  2. Pierre HabouzitJun 13, 2007
  3. Pierre HabouzitJun 13, 2007
  4. Pierre HabouzitJun 13, 2007
  5. Bill LearJun 13, 2007
  6. Pierre HabouzitJun 13, 2007
  7. Randal L. SchwartzJun 13, 2007
  8. Alex RiesenJun 13, 2007
  9. Randal L. SchwartzJun 13, 2007
  10. Alex RiesenJun 13, 2007
  11. Randal L. SchwartzJun 13, 2007
  12. Alex RiesenJun 13, 2007
  13. Randal L. SchwartzJun 13, 2007
  14. Alex RiesenJun 13, 2007
  15. Johannes SchindelinJun 13, 2007
  16. Andy ParkinsJun 13, 2007
  17. Johannes SchindelinJun 13, 2007
  18. Bill LearJun 13, 2007
  19. Johannes SchindelinJun 13, 2007
  20. Bill LearJun 13, 2007
  21. Junio C HamanoJun 13, 2007
  22. Daniel BarkalowJun 14, 2007
  23. Linus TorvaldsJun 14, 2007
  24. Junio C HamanoJun 14, 2007
  25. Raimund BauerJun 14, 2007
  26. Steven GrimmJun 14, 2007
  27. Nicolas PitreJun 14, 2007
  28. Bill LearJun 14, 2007
  29. Linus TorvaldsJun 14, 2007
  30. Olivier GalibertJun 14, 2007
  31. Linus TorvaldsJun 14, 2007
  32. Martin LanghoffJun 15, 2007
  33. Linus TorvaldsJun 15, 2007
  34. Martin LanghoffJun 15, 2007
  35. Robin RosenbergJun 15, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.