threads / discuss / 36872

Re: Git reset --hard with staged changes

Subject: Re: Git reset --hard with staged changes

## tl;dr

9 messages between Jun 9, 2014 and Jun 10, 2014.

replies: 8people: 4as markdown or json

Pierre-François CLEMENT· Jun 9, 2014, 11:24 UTC · lore
Hi all,

Someone pointed out on the "Git for human beings" Google group (https://groups.google.com/d/topic/git-users/27_FxIV_100/discussion) that using git-reset's hard mode when having staged untracked files simply deletes them from the working dir.

Since git-reset specifically doesn't touch untracked files, one could expect having staged untracked files reset to their previous "untracked" state rather than being deleted.

Could this be a bug or a missing feature? Or if it isn't, can someone explain what we got wrong? Cheers

-- Pierre-François CLEMENT Application developer at Upcast Social

David Kastrup· Jun 9, 2014, 14:04 UTC · re: Pierre-François CLEMENT · lore
Pierre-François CLEMENT <likeyn@gmail.com> writes:
Show 13 quoted lines
> Hi all,
>
> Someone pointed out on the "Git for human beings" Google group
> (https://groups.google.com/d/topic/git-users/27_FxIV_100/discussion)
> that using git-reset's hard mode when having staged untracked files
> simply deletes them from the working dir.
>
> Since git-reset specifically doesn't touch untracked files, one could
> expect having staged untracked files reset to their previous
> "untracked" state rather than being deleted.
>
> Could this be a bug or a missing feature? Or if it isn't, can someone
> explain what we got wrong?
git reset --keep maybe?
In a work dir and index without modifications, I expect

git apply --index ... git reset --hard

to remove any files that git apply created. It would not do so using your proposal. I agree that it seems a bit of a borderline, but I consider it better that once a file _is_ tracked, git reset --hard will first physically remove it before untracking it.

-- 
David Kastrup
Pierre-François CLEMENT· Jun 9, 2014, 23:22 UTC · re: David Kastrup · lore
2014-06-09 16:04 GMT+02:00 David Kastrup <dak@gnu.org>:
Show 30 quoted lines
> Pierre-François CLEMENT <likeyn@gmail.com> writes:
>
>> Hi all,
>>
>> Someone pointed out on the "Git for human beings" Google group
>> (https://groups.google.com/d/topic/git-users/27_FxIV_100/discussion)
>> that using git-reset's hard mode when having staged untracked files
>> simply deletes them from the working dir.
>>
>> Since git-reset specifically doesn't touch untracked files, one could
>> expect having staged untracked files reset to their previous
>> "untracked" state rather than being deleted.
>>
>> Could this be a bug or a missing feature? Or if it isn't, can someone
>> explain what we got wrong?
>
> git reset --keep maybe?
>
> In a work dir and index without modifications, I expect
>
> git apply --index ...
> git reset --hard
>
> to remove any files that git apply created.  It would not do so using
> your proposal.  I agree that it seems a bit of a borderline, but I
> consider it better that once a file _is_ tracked, git reset --hard will
> first physically remove it before untracking it.
>
> --
> David Kastrup

Hm, I didn't think of "git apply --index"... Makes sense for this special use, but I'm not sure about the other use cases. Consider this scenario:

You create a new (untracked) file. You use git-reset's hard mode to go one commit back, the new (untracked) file's still there. You add/stage that new file. You use git-reset's hard mode again to go one commit back, and the new untracked file you just staged gets deleted.

Also, according to Git-scm (http://git-scm.com/book/en/Git-Basics-Recording-Changes-to-the-Repository):

"Tracked files are files that were in the last snapshot [...]. Untracked files are everything else."

So it seems to me like staged untracked files shouldn't be considered as tracked files, and thus shouldn't be removed. Or maybe, git-reset's hard mode should always delete everything including untracked files? It would also make sense, given the numerous modes it has.

-- Pierre-François CLEMENT Application developer at Upcast Social

Junio C Hamano· Jun 9, 2014, 23:28 UTC · re: Pierre-François CLEMENT · lore
Pierre-François CLEMENT <likeyn@gmail.com> writes:
> Hm, I didn't think of "git apply --index"... Makes sense for this
> special use, but I'm not sure about the other use cases.

Try merging another branch that tracks a file your current branch does not know about and ending up with conflicts during that merge. Resetting the half-done result away must remove that new path from your working tree and the index.

Pierre-François CLEMENT· Jun 10, 2014, 14:59 UTC · re: Junio C Hamano · lore
2014-06-10 1:28 GMT+02:00 Junio C Hamano <gitster@pobox.com>:
Show 9 quoted lines
> Pierre-François CLEMENT <likeyn@gmail.com> writes:
>
>> Hm, I didn't think of "git apply --index"... Makes sense for this
>> special use, but I'm not sure about the other use cases.
>
> Try merging another branch that tracks a file your current branch
> does not know about and ending up with conflicts during that merge.
> Resetting the half-done result away must remove that new path from
> your working tree and the index.

Hm I see. Even though the documentation doesn't make it very clear about what happens to such files, it turns out the scenario we stumbled upon seems to be the special use case after all. Thanks for shedding some light on this :) I wonder why does git-reset's hard mode not always remove untracked files then? -- Pierre-François CLEMENT Application developer at Upcast Social

David Kastrup· Jun 10, 2014, 15:27 UTC · re: Pierre-François CLEMENT · lore
Pierre-François CLEMENT <likeyn@gmail.com> writes:
Show 16 quoted lines
> 2014-06-10 1:28 GMT+02:00 Junio C Hamano <gitster@pobox.com>:
>> Pierre-François CLEMENT <likeyn@gmail.com> writes:
>>
>>> Hm, I didn't think of "git apply --index"... Makes sense for this
>>> special use, but I'm not sure about the other use cases.
>>
>> Try merging another branch that tracks a file your current branch
>> does not know about and ending up with conflicts during that merge.
>> Resetting the half-done result away must remove that new path from
>> your working tree and the index.
>
> Hm I see. Even though the documentation doesn't make it very clear
> about what happens to such files, it turns out the scenario we
> stumbled upon seems to be the special use case after all. Thanks for
> shedding some light on this :) I wonder why does git-reset's hard mode
> not always remove untracked files then?

Because it never removes them? Git only removes files once it tracks them. This includes the operation of removing _and_ untracking them, like with git reset --hard.

The only command which explicitly messes with untracked files is git-clean.

-- 
David Kastrup
Pierre-François CLEMENT· Jun 10, 2014, 16:30 UTC · re: David Kastrup · lore
2014-06-10 17:27 GMT+02:00 David Kastrup <dak@gnu.org>:
Show 28 quoted lines
> Pierre-François CLEMENT <likeyn@gmail.com> writes:
>
>> 2014-06-10 1:28 GMT+02:00 Junio C Hamano <gitster@pobox.com>:
>>> Pierre-François CLEMENT <likeyn@gmail.com> writes:
>>>
>>>> Hm, I didn't think of "git apply --index"... Makes sense for this
>>>> special use, but I'm not sure about the other use cases.
>>>
>>> Try merging another branch that tracks a file your current branch
>>> does not know about and ending up with conflicts during that merge.
>>> Resetting the half-done result away must remove that new path from
>>> your working tree and the index.
>>
>> Hm I see. Even though the documentation doesn't make it very clear
>> about what happens to such files, it turns out the scenario we
>> stumbled upon seems to be the special use case after all. Thanks for
>> shedding some light on this :) I wonder why does git-reset's hard mode
>> not always remove untracked files then?
>
> Because it never removes them?  Git only removes files once it tracks
> them.  This includes the operation of removing _and_ untracking them,
> like with git reset --hard.
>
> The only command which explicitly messes with untracked files is
> git-clean.
>
> --
> David Kastrup

Yeah sorry, I just noticed the emails on the definition of what are (un)tracked files (http://thread.gmane.org/gmane.comp.version-control.git/251071/focus=251151), as I didn't get them in my inbox for some reason. So staged files which aren't in HEAD are also considered tracked -- which explains it all. Someone told me that too on the "Git for human beings" Google Group, but I couldn't find a definition that backs this in the man pages (maybe the git-glossary would be a good place for it?), and the one from the Git-Scm book only confused me in thinking the opposite. Thanks for the clarification

-- Pierre-François CLEMENT Application developer at Upcast Social

Dale Worley· Jun 10, 2014, 01:03 UTC · re: Pierre-François CLEMENT · lore
From: Pierre-François CLEMENT <likeyn <at> gmail.com>
Show 17 quoted lines
> You create a new (untracked) file.
> You use git-reset's hard mode to go one commit back, the new
> (untracked) file's still there.
> You add/stage that new file.
> You use git-reset's hard mode again to go one commit back, and the new
> untracked file you just staged gets deleted.
> 
> Also, according to Git-scm
> (http://git-scm.com/book/en/Git-Basics-Recording-Changes-to-the-Repository):
> 
> "Tracked files are files that were in the last snapshot [...].
> Untracked files are everything else."
> 
> So it seems to me like staged untracked files shouldn't be considered
> as tracked files, and thus shouldn't be removed. Or maybe, git-reset's
> hard mode should always delete everything including untracked files?
> It would also make sense, given the numerous modes it has.

There's a core question that must be answered: What, *exactly*, is a "tracked file"?

If you look at that passage in the book, it continues:

"Tracked files are files that were in the last snapshot; they can be unmodified, modified, or staged. Untracked files are everything else — any files in your working directory that were not in your last snapshot and are not in your staging area."

But if you look carefully, that passage gives two definitions of "untracked files", and *they don't agree*, specifically in the case of a file that is in the index but not in the base commit. And that's the case we're considering.

To fix this, you've got to figure out what the definition of "tracked file" is supposed to be, and then ensure that everything (code and documentation) is consistent with that.

(As far as I can tell from Git's behavior, the definition of tracked file is "any file that is in the base commit or in the index". Based on that definition, "git reset --hard" is working as documented.)

Dale
Junio C Hamano· Jun 10, 2014, 05:44 UTC · re: Dale Worley · lore
Dale Worley <worley@alum.mit.edu> writes:
> (As far as I can tell from Git's behavior, the definition of tracked file is
> "any file that is in the base commit or in the index".  Based on that
> definition, "git reset --hard" is working as documented.)

The book (whichever book you guys are talking about) is wrong, if it considers only the paths in the HEAD commit tracked. After the user deliberately does "git add" a path not in HEAD, the user runs any command (e.g. "git apply --index", "git cherry-pick --no-commit") that may bring a path not in HEAD to the result without recording a new commit that updates the HEAD, a new path is recorded in the index and that path is considered "tracked" before the resulting contents in the index is made into a commit.

← back to recent threads