From: Jeff King <peff@peff.net>
To: Tzu-Jung Lee <roylee17@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: git-checkout silently throws away the dirty status of index without a warning?
Date: Thu, 1 Sep 2011 12:56:38 -0400 [thread overview]
Message-ID: <20110901165638.GE15018@sigill.intra.peff.net> (raw)
In-Reply-To: <CAEvN+1h+mY+f3dzK7LFOwkqokOZSS-LosCzBqtYGbyjz=Dg7Zw@mail.gmail.com>
On Thu, Sep 01, 2011 at 11:47:59PM +0800, Tzu-Jung Lee wrote:
> Correct me if I'm wrong:
>
> git-checkout saves the changes to index and working-tree, and
> tries to apply them to the destined commit.
> If the changes are applicable, then git-checkout the destined
> commit and apply the changes.
> Otherwise, git-checkout fails with warnings and leaves the current
> status untouched.
Not exactly. "git checkout <branch>" will switch your HEAD to <branch>,
and then try to make your index and working tree match the contents of
<branch>, with two exceptions:
1. If you have local changes in a file, but the contents of the file
in <branch> do not differ from what's in the current HEAD, then the
file will be left alone (i.e., your local changes will be
preserved).
2. If you have local changes in a file, and the contents of the file
in <branch> differ both from what's in your working tree and from
what's in your current HEAD, git will print an error and refuse to
overwrite your changes (though you can ask it to merge them with
"git checkout -m").
So it is not about "do these changes apply", but rather that we will
give up any time file-level merging is required (unless "-m" is
specified).
The other form, "git checkout <branch> [--] <file>", is not about
switching branches at all, but about putting content from <branch> into
the current index and working tree, overwriting what's there.
> If the above correct. Please help me clarify if the following corner
> case an intended or unexpected behavior.
> [...]
> $ git checkout -b br1
> $ git reset HEAD^
> Unstaged changes after reset:
> M aaa.txt
> M bbb.txt
So you have changes in two commits...
> $ git checkout HEAD aaa.txt
And here you explicitly overwrite the changes in aaa.txt.
> $ git status --short
> M bbb.txt
...leaving only the changes in bbb.txt.
> $ git add bbb.txt
> $ git status
>
> # On branch br1
> # Changes to be committed:
> # (use "git reset HEAD <file>..." to unstage)
> #
> # modified: bbb.txt
> #
OK, now it's staged.
> $ git checkout master
> Switched to branch 'master'
>
> git silently switch to master without warning against the index are
> "RESTORE/RESET" to clean.
Yes, because the changes in your index were identical to what was in the
destination branch. So we didn't drop any changes; they're still in the
index and in the working tree. It's simply that when compared to your
new HEAD, they are uninteresting.
> $ git checkout br1
> $ git status
> # On branch br1
> nothing to commit (working directory clean)
And now when we switch to br1, you have no changes against master in
your working tree or index, so there is no dirty state to block
switching branches.
I think git is working as intended here. I agree it is a somewhat
surprising corner case, but only because your changes happened to
exactly match the difference between the two branches you are switching
between. But it makes sense when you think about what "dirty state"
means: it is differences between HEAD and your index and working tree.
So we usually think of creating or removing dirty state by changing the
working tree. But you could equally well do it by changing the HEAD
without changing the working tree, which is what you did here.
-Peff
next prev parent reply other threads:[~2011-09-01 16:56 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-01 15:47 git-checkout silently throws away the dirty status of index without a warning? Tzu-Jung Lee
2011-09-01 16:56 ` Jeff King [this message]
2011-09-01 17:50 ` Tzu-Jung Lee
2011-09-01 17:11 ` Junio C Hamano
2011-09-01 18:28 ` Tzu-Jung Lee
2011-09-02 1:52 ` Andrew Ardill
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=20110901165638.GE15018@sigill.intra.peff.net \
--to=peff@peff.net \
--cc=git@vger.kernel.org \
--cc=roylee17@gmail.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).