threads / discuss / 40214

"git checkout" resets modified files

Subject: "git checkout" resets modified files

## tl;dr

3 messages between Aug 29, 2015 and Aug 29, 2015.

replies: 2people: 2as markdown or json

Steve Heyns· Aug 29, 2015, 06:15 UTC · lore
"git checkout" resets modified files
Version git  2.5.0,

Description: I was automating a process that would pull and switch to another branch when I stumbled across this. I have not been able to emulate this from command line but using go (or I imagine other languages are similar) if you execute a command like

exec.Command("git","checkout","")
A checkout with the branch parameter but the branch parameter is empty.

The result is git resets the the repository, modified files are reset back to original state without warning.

I would expect the behavior should be the same as a "git checkout" command

Has anyone else seen something like this ? For myself the solution was to simply suppress passing in the revision as a third argument if the revision was empty. But this does appear to be an off behavior.

Thanks Nz

Junio C Hamano· Aug 29, 2015, 07:15 UTC · re: Steve Heyns · lore

Re: "git checkout" resets modified files

Steve Heyns <notzippy@gmail.com> writes:
Show 13 quoted lines
> "git checkout" resets modified files
>
> Version git  2.5.0,
>
> Description:
> I was automating a process that would pull and switch to another
> branch when I stumbled across this. I have not been able to emulate
> this from command line but using go (or I imagine other languages are
> similar) if you execute a command like
>
> exec.Command("git","checkout","")
>
> A checkout with the branch parameter but the branch parameter is empty.

It is not feeding an empty branch parameter [*1*]. It is asking Git to check out all paths that match a pathspec "" out of the index.

Now, arguably, the user who would want to match everything may be more likely to give "." as the pathspec (or if she is not at the root of the working tree, ":/"), but "" means the same thing as ".", and the requested behaviour "check out all that match this pathspec from the index" would essentially mean "I want to get rid of all the modification in my working tree relative to the index".

I do not think this behaviour depends on the vintage of Git. An empty string as pathspec has always matched "everything in here" AFAIR.

[Footnote]
*1* Checking out a branch whose name is an empty string can be asked
    explicitly by disambiguating double-dash like this:
    $ git checkout "" --
And it will be answered (correctly) with:
    fatal: invalid reference
Junio C Hamano· Aug 29, 2015, 07:58 UTC · re: Junio C Hamano · lore

Re: "git checkout" resets modified files

Junio C Hamano <gitster@pobox.com> writes:
> I do not think this behaviour depends on the vintage of Git.  An
> empty string as pathspec has always matched "everything in here"
> AFAIR.

Having said all that, I think the DWIM used by "git checkout" has some room for improvement, namely, its "we didn't see a double-dash; is it a ref or is it a pathspec?" disambiguation should become similar to the revision parser's.

Notice that
    $ git log ""

will error out, saying that an empty string does not name either a revision or an existing path in the working tree. I think the same "refusal due to ambiguity" should be in "git checkout" when the user says

    $ git checkout ""

Right now, when there is no double-dash, the code checks if the first token X can be DWIMmed as a ref. It may either name an existing branch X, or it may be a non-existing branch name, but there is a single remotes/Y/X and the user is too lazy to say 'git checkout -t -b remotes/Y/X X' and instead said 'git checkout X'.

And if the first token X cannot be DWIMmed as a ref according to the above logic, unlike the revision parser, we do not check it (and all the subsequent tokens) name existing filesystem entity.

I think we really should. With that, Steve's command line would have correctly diagnosed as a liely error.

Of course, that still allows people to say
    $ git checkout -- ""
if they really mean it, but they can type
    $ git checkout -- :/
just as easily, so there is no big loss.

After following the existing code myself, I think this is a rather easy low-hanging fruit for any aspiring Git hacker. Hint, hint...

Show 10 quoted lines
> [Footnote]
>
> *1* Checking out a branch whose name is an empty string can be asked
>     explicitly by disambiguating double-dash like this:
>
>     $ git checkout "" --
>
> And it will be answered (correctly) with:
>
>     fatal: invalid reference

← back to recent threads