From: Michael Witten <mfwitten@gmail.com>
To: Markus Elfring <Markus.Elfring@web.de>
Cc: git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>
Subject: Re: Better cooperation between checkouts and stashing
Date: Mon, 01 Mar 2010 09:02:39 -0800 (PST) [thread overview]
Message-ID: <4b8bf32f.0706c00a.26cb.691d@mx.google.com> (raw)
In-Reply-To: <4B8B9BF1.10408@web.de>
To Junio in particular: See the very bottom of this email.
On Mon, Mar 1, 2010 at 04:50, Markus Elfring <Markus.Elfring@web.de> wrote:
>> - The branch you happen to have checked out was 'next', but the solution
>> is a bugfix, and should go to 'maint'.
>>
>> Now, at this point, you want to checkout 'maint' without losing your local
>> change. The paths you touched with your quick fix are often not different
>> between the two branches, and "checkout maint" will checkout the branch
>> while keeping your local changes intact.
>
> Does the wording in the manual fit to the mentioned software development practice?
>
> "When <paths> are not given, this command switches branches by updating the
> index, working tree, and HEAD to reflect the specified branch."
>
> I see a need for further clarifications of the involved details.
Junio pointed out that the documentation is currently lacking:
[Unfortunately,] I don't see anything that states
clearly that "checkout" is designed to carry your
local changes across in any documentation (I gave
a cursory look to the user manual, tutorial and
checkout manual page). Probably "git checkout --help"
needs a "Switching branches" section, just like the
planned enhancement for "Detached HEAD" section.
In other words, the documentation NEEDS to be updated to include
the explanation and rationale that Junio also supplied:
Checking out another branch (branch switching) is
designed to carry your local modification across
with you. This is to allow you to start working on
something, realize that your changes are better suited
for another branch, and at that point after the fact
"git checkout" that other branch, while keeping what
you have done so far.
If the original branch you started your work from and
the branch you are checking out have different contents
in files you have changed (aka "your changes conflict
at the paths level"), without -m option, "git checkout"
refuses to check out the other branch, because it will
need a three-way merge to carry your changes forward,
and you might not be prepared to resolve conflicts
resulting from such a merge.
In practice, however, your changes often don't conflict
with the changes between the branches at the paths
level, and "git checkout" lets you carry your local
changes across just fine. I'd say this is the majority
of the case especially for experienced git users, as
they tend to commit in smaller and more logical units
than those from other SCM background.
and Junio expanded on this later:
It is important to understand that a local change does
not belong to your current branch (it does not belong to
_any_ branch). It belongs to you, and you can take it
around while switching between branches. And that is a
big time-saving feature.
This lets you work like this:
- You are reading a mailing list message that
asks for help, and you know the solution---you
can give the help real quick.
- You hack in whatever branch that happen to be
checked out. The change is perfect, it works.
- The branch you happen to have checked out
was 'next', but the solution is a bugfix, and
should go to 'maint'.
Now, at this point, you want to checkout 'maint' without
losing your local change. The paths you touched with
your quick fix are often not different between the two
branches, and "checkout maint" will checkout the branch
while keeping your local changes intact. All that is
left for you to do is to run another round of test to
make sure that your fix didn't depend on anything not
in 'maint' and commit the change with appropriate log
message, and then you can go back to whatever you were
doing with "checkout next".
When the change involves paths that were touched
between 'maint' and 'next', of course you won't be
able to switch without merging the local change to the
difference between 'next' and 'maint'. There are a few
workflows to deal with such a case, and the easiest is
"checkout -m", if you are confident that you can resolve
it.
In a case where "checkout -m" would result in a conflict
too big to resolve, the original fix you made would not
be applicable to 'maint' (iow, you should have solved it
differently starting from 'maint'), and you may end up
doing "reset --hard" and start from scratch, but that is
a rare worst case.
I said it is rare, because you would notice, while doing
the "quick fix" based on 'next' codebase, that the code
you are touching have changed since 'maint' and won't be
applicable to its final destination (by that time you
know you are "fixing"), and you won't waste too much
time continuing to work in a checkout of 'next'.
I think it would be a great contribution if you could clean up
Junio's explanation and submit a patch that includes it in the
documentation for "git checkout".
> - Would it be useful if it will become configurable if the corresponding
> contents will also be automatically restored by a checkout?
>From what you've said, I think you essentially want to implement
"git checkout" with something like the following (this hack is **not**
meant as a solution; it is only meant to illustrate what I think is
Markus Elfring's desire):
# Utility:
get_stash_id()
{
local branch=$(git rev-parse --symbolic-full-name HEAD)
[ $branch = HEAD ] && return 1 # don't stash for detached HEAD
echo -n "$branch" | md5sum | awk -F" " '{print $1}'
}
# New implementation:
checkout()
{
# Stash local modifications (including index modifications) if
# necessary, using an easily identifiable message known as the
# 'stash id':
local stash_id
stash_id=$(get_stash_id) &&
git stash save -q "$stash_id" || # Save local modifications
git reset --hard HEAD # Throw away changes on detached HEAD
# Do the checkout that was requested:
git checkout "$@"
# Unstash previously stashed local modifications (including
# index modifications) if they were automatically stashed
# before (the lookup is done with the relevant 'stash id'):
stash_id=$(get_stash_id) &&
stash_id=$(git stash list | awk -F': ' "/$stash_id/ {print \$1}") &&
[ -n "$stash_id" ] &&
git stash pop --index "$stash_id"
}
Sincerely,
Michael Witten
next prev parent reply other threads:[~2010-03-01 17:02 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-01 18:50 Better cooperation between checkouts and stashing Markus Elfring
2010-02-01 20:40 ` Junio C Hamano
2010-02-01 21:57 ` Markus Elfring
2010-02-01 22:44 ` Eugene Sajine
2010-02-02 1:36 ` Petr Baudis
2010-02-02 10:26 ` Markus Elfring
2010-02-02 11:04 ` Petr Baudis
2010-02-09 19:20 ` Markus Elfring
2010-02-09 20:06 ` Junio C Hamano
2010-02-09 21:01 ` Markus Elfring
2010-02-18 17:43 ` Markus Elfring
2010-02-18 20:09 ` Junio C Hamano
2010-02-27 21:33 ` Markus Elfring
2010-02-27 21:51 ` Junio C Hamano
2010-02-28 13:55 ` Markus Elfring
2010-02-28 22:57 ` Michael Witten
2010-03-01 10:50 ` Markus Elfring
2010-03-01 17:02 ` Michael Witten [this message]
2010-03-01 17:23 ` Junio C Hamano
2010-03-01 18:14 ` Michael Witten
2010-03-01 18:29 ` Markus Elfring
2010-03-01 19:44 ` Junio C Hamano
2010-03-01 21:20 ` Markus Elfring
2010-03-02 1:41 ` Michael Witten
2010-03-02 9:35 ` Markus Elfring
2010-03-02 17:50 ` Junio C Hamano
2010-03-03 15:55 ` Markus Elfring
2010-03-04 7:46 ` Michael Witten
2010-03-04 19:55 ` Markus Elfring
2010-03-02 9:45 ` Markus Elfring
2010-03-02 18:05 ` Junio C Hamano
2010-03-03 16:00 ` Markus Elfring
2010-03-17 16:35 ` [PATCH] Clarification for the command "git checkout <branch>" Markus Elfring
2010-03-17 16:44 ` Avery Pennarun
2010-03-17 17:00 ` Markus Elfring
2010-03-17 17:58 ` Junio C Hamano
2010-03-17 18:21 ` Markus Elfring
2010-03-17 18:37 ` Junio C Hamano
2010-03-17 18:50 ` Michael Witten
2010-03-17 19:23 ` Junio C Hamano
2010-03-18 10:11 ` Markus Elfring
2010-03-18 16:36 ` Avery Pennarun
2010-03-18 17:19 ` Michael Witten
2010-03-18 17:33 ` Avery Pennarun
2010-03-19 8:28 ` Markus Elfring
2010-03-19 17:17 ` Avery Pennarun
2010-03-20 6:00 ` Markus Elfring
2010-03-19 8:15 ` Markus Elfring
2010-03-30 15:57 ` Markus Elfring
2010-03-30 22:13 ` Junio C Hamano
2010-03-31 3:58 ` Ramkumar Ramachandra
2010-04-01 4:52 ` Junio C Hamano
2010-04-01 13:09 ` Ramkumar Ramachandra
2010-04-01 6:38 ` Markus Elfring
2010-04-10 13:30 ` Markus Elfring
2010-04-10 22:31 ` Junio C Hamano
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=4b8bf32f.0706c00a.26cb.691d@mx.google.com \
--to=mfwitten@gmail.com \
--cc=Markus.Elfring@web.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.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;
as well as URLs for NNTP newsgroup(s).