Re: pull into dirty working tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Johannes Schindelin <Johannes.Schindelin@xxxxxx> writes:

> 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.

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux