From: Junio C Hamano <junkio@cox.net>
To: Steven Grimm <koreth@midwinter.com>
Cc: git@vger.kernel.org
Subject: Re: Working copy as a pseudo-head
Date: Mon, 27 Nov 2006 01:20:39 -0800 [thread overview]
Message-ID: <7vlklxi6u0.fsf@assigned-by-dhcp.cox.net> (raw)
In-Reply-To: <456A9F93.1060801@midwinter.com> (Steven Grimm's message of "Mon, 27 Nov 2006 00:19:31 -0800")
Steven Grimm <koreth@midwinter.com> writes:
> Comments? Is this just nuts?
It is not "nuts", but we do not do it currently because it is a
bit too combersome to make it recoverable when things go wrong
while keeping the cost of making the necessary back-up for
recovery low. When switching branches with local changes,
"git-checkout -m" needs to deal with a similar issue, but that
case only deal with two trees and a working tree. To do this
for three-way merge, the conflicts you need to deal with become
more complex.
What needs to be done is very simple and straightforward. You
first stash away the working tree state in a "virtual" tree,
then perform the usual 3-way merge using the common ancestor,
your HEAD and the other head, and come up with the merge result
without any of your changes. Then you run another three-way
merge between the merge result and your previous working tree
state using the HEAD before the merge as the common ancestor.
o---o---X (other head)
/
---o---o---H (your head)
\
W (your working tree)
==>
o---o---X (other head)
/ \
---o---o---H---M (merge between the base trees)
\
W (your working tree)
==>
o---o---X (other head)
/ \
---o---o---H---M (merge between the base trees)
\ \
W---W'(your working tree, updated for the merge result)
The design goal here is that you do not want to get any of your
local changes (i.e. "diff H W") to be included when you record
the result of the base merge 'M', and you would want the diff
between H and W to be forward-ported to the diff between M and
W'.
The first goal is already quite cumbersome when the merge
between X and H involve conflicing merges. We use the working
tree to perform the file level merge (i.e. you edit them with
your favorite editor, and tell git when you are done), so while
that is happening we temporarily need to remove what was between
H and W. If the merge is too complex and the user decides to
revert the whole thing, we would need to rewind the index and
working tree to the state at W (that means we would at least
need to stash the diff between H and index, and index and
working tree before starting the merge).
After the base merge is done, we would need to update the HEAD
to point at M. Then we would perform the second three-way merge
between M and W using the original HEAD as their common
ancestor to come up with W'. When this conflicts, there is no
easy way for the user to recover, other than going back to the
original state (that is, HEAD points at H and working tree is
W), even after having spent effort to merge between X and H to
produce M.
In common usage (call that "best current practice" if you may),
you do not have local changes in the working tree that would
conflict with the merge, so the current behaviour feels
cumbersome only when the safety valve kicks in. After seeing it
fail due to the safety valve, you can do the same as what the
above pictures depict using existing tools.
* preserve the local changes (i.e. come up with the virtual
"W"):
git commit -a -m WIP
git tag -f WIP
git reset --hard HEAD^
* perform the merge in the now-clean tree:
git pull ;# again from the same place
edit edit
test test
git commit -a ;# resolve conflicts, test and commit
* recover what you have preserved, and discard the virtual W:
git pull --no-commit . WIP ;# merge in
git reset ;# revert index to HEAD aka base merge result.
git tag -d WIP
prev parent reply other threads:[~2006-11-27 9:20 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-27 8:19 Working copy as a pseudo-head Steven Grimm
2006-11-27 9:20 ` Junio C Hamano [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7vlklxi6u0.fsf@assigned-by-dhcp.cox.net \
--to=junkio@cox.net \
--cc=git@vger.kernel.org \
--cc=koreth@midwinter.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox