git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* Re: Git reset --hard with staged changes
       [not found] <CANWD=rWmzgAwTp=E_1=th0Myk-dh4m5Y9PE3=fpHeirsVVQKwQ@mail.gmail.com>
@ 2014-06-09 11:24 ` Pierre-François CLEMENT
  2014-06-09 14:04   ` David Kastrup
  0 siblings, 1 reply; 17+ messages in thread
From: Pierre-François CLEMENT @ 2014-06-09 11:24 UTC (permalink / raw)
  To: git

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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2014-06-09 11:24 ` Pierre-François CLEMENT
@ 2014-06-09 14:04   ` David Kastrup
  2014-06-09 23:22     ` Pierre-François CLEMENT
  0 siblings, 1 reply; 17+ messages in thread
From: David Kastrup @ 2014-06-09 14:04 UTC (permalink / raw)
  To: Pierre-François CLEMENT; +Cc: git

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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2014-06-09 14:04   ` David Kastrup
@ 2014-06-09 23:22     ` Pierre-François CLEMENT
  2014-06-09 23:28       ` Junio C Hamano
  2014-06-10  1:03       ` Dale Worley
  0 siblings, 2 replies; 17+ messages in thread
From: Pierre-François CLEMENT @ 2014-06-09 23:22 UTC (permalink / raw)
  To: David Kastrup; +Cc: git

2014-06-09 16:04 GMT+02:00 David Kastrup <dak@gnu.org>:
> 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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2014-06-09 23:22     ` Pierre-François CLEMENT
@ 2014-06-09 23:28       ` Junio C Hamano
  2014-06-10 14:59         ` Pierre-François CLEMENT
  2014-06-10  1:03       ` Dale Worley
  1 sibling, 1 reply; 17+ messages in thread
From: Junio C Hamano @ 2014-06-09 23:28 UTC (permalink / raw)
  To: Pierre-François CLEMENT; +Cc: David Kastrup, git

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.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2014-06-09 23:22     ` Pierre-François CLEMENT
  2014-06-09 23:28       ` Junio C Hamano
@ 2014-06-10  1:03       ` Dale Worley
  2014-06-10  5:44         ` Junio C Hamano
  1 sibling, 1 reply; 17+ messages in thread
From: Dale Worley @ 2014-06-10  1:03 UTC (permalink / raw)
  To: git

From: Pierre-François CLEMENT <likeyn <at> gmail.com>
> 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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2014-06-10  1:03       ` Dale Worley
@ 2014-06-10  5:44         ` Junio C Hamano
  0 siblings, 0 replies; 17+ messages in thread
From: Junio C Hamano @ 2014-06-10  5:44 UTC (permalink / raw)
  To: Dale Worley; +Cc: git

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.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2014-06-09 23:28       ` Junio C Hamano
@ 2014-06-10 14:59         ` Pierre-François CLEMENT
  2014-06-10 15:27           ` David Kastrup
  0 siblings, 1 reply; 17+ messages in thread
From: Pierre-François CLEMENT @ 2014-06-10 14:59 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: David Kastrup, git

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?
--
Pierre-François CLEMENT
Application developer at Upcast Social

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2014-06-10 14:59         ` Pierre-François CLEMENT
@ 2014-06-10 15:27           ` David Kastrup
  2014-06-10 16:30             ` Pierre-François CLEMENT
  0 siblings, 1 reply; 17+ messages in thread
From: David Kastrup @ 2014-06-10 15:27 UTC (permalink / raw)
  To: Pierre-François CLEMENT; +Cc: Junio C Hamano, git

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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2014-06-10 15:27           ` David Kastrup
@ 2014-06-10 16:30             ` Pierre-François CLEMENT
  0 siblings, 0 replies; 17+ messages in thread
From: Pierre-François CLEMENT @ 2014-06-10 16:30 UTC (permalink / raw)
  To: David Kastrup; +Cc: Junio C Hamano, git

2014-06-10 17:27 GMT+02:00 David Kastrup <dak@gnu.org>:
> 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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
@ 2016-05-23  0:55 Yotam Gingold
  2016-05-23 17:05 ` Junio C Hamano
  2016-05-23 19:31 ` Christian Couder
  0 siblings, 2 replies; 17+ messages in thread
From: Yotam Gingold @ 2016-05-23  0:55 UTC (permalink / raw)
  To: git

Pierre-François CLEMENT <likeyn <at> gmail.com> writes:
> 2014-06-10 17:27 GMT+02:00 David Kastrup <dak <at> gnu.org>:
>> Pierre-François CLEMENT <likeyn <at> gmail.com> writes:
>>
>>> ...
>>>
>>> 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
> 
> ... 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

Jumping into this conversation two years later*. There's confusion about what
constitutes a tracked file for git reset --hard, and good reasons for git reset
--hard's behavior. Nevertheless, I think we can all agree that the man page
entry for git reset --hard is woefully deficient:

--hard Resets the index and working tree. Any changes to tracked files in the
working tree since <commit> are discarded.

This should be clarified to define what a tracked file is. I propose appending:

    A file is considered tracked if it exists in a prior commit or in the
    staging area. Note that a newly added file not in any prior commit will be
    removed.

I would also like to propose that the staging area's tree object be saved,
perhaps in the reflog or perhaps just as a dangling object. This would allow
graceful recovery from git reset --hard. Witness the many questions and answers
on recovery:
    http://stackoverflow.com/questions/7374069/undo-git-reset-hard-with-uncommitted-files-in-the-
staging-area
    http://stackoverflow.com/questions/5788037/recover-from-git-reset-hard
    http://stackoverflow.com/questions/5473/how-can-i-undo-git-reset-hard-head1
    http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html
    https://bani.com.br/2014/10/recovering-lost-files-after-a-git-reset-hard/
    https://medium.com/@CarrieGuss/how-to-recover-from-a-git-hard-reset-b830b5e3f60c

All of these solutions recover the contents of files, but not their names or the
directory structure. Saving the tree object somewhere (anywhere!) would solve
this problem.

I was bitten by this in a vicious way. I was setting up a new repository for a
bunch of code and data (git init; git add .), changed my mind about adding the
data (git reset --hard), and nearly lost everything. The only tree object that
could be found was an empty one, so I got file contents without names or
directories (not good, because experimental conditions for the data were encoded
in the directory structure).

Cheers,
Yotam

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2016-05-23  0:55 Git reset --hard with staged changes Yotam Gingold
@ 2016-05-23 17:05 ` Junio C Hamano
  2016-05-23 19:31 ` Christian Couder
  1 sibling, 0 replies; 17+ messages in thread
From: Junio C Hamano @ 2016-05-23 17:05 UTC (permalink / raw)
  To: Yotam Gingold; +Cc: git

Yotam Gingold <yotam@yotamgingold.com> writes:

> --hard Resets the index and working tree. Any changes to tracked files in the
> working tree since <commit> are discarded.
>
> This should be clarified to define what a tracked file is.

A "tracked file" in that sentence is a file that is not untracked, I
think.

There are only four cases, so let's enumerate:

 * A path that is in HEAD but not in the index.  "reset --hard"
   wants to make the resulting index match what is in HEAD, so
   the path is added back to the index.  "reset --hard" also wants
   to make the resulting working tree match what is in the index, so
   the path in the working tree will be overwritten (or created, if
   you removed it earlier) with the contents taken from HEAD.

 * A path that is in HEAD and also in the index.  "reset --hard"
   wants to make the resulting index match what is in HEAD, and it
   also wants to make the resulting working tree match what is in
   the index, so any changes to the index and the working tree will
   be overwritten by the contents taken from HEAD.

 * A path that is not in HEAD but in the index.  The path is removed
   from the index and from the working tree, due to the same logic
   as the previous two.

 * A path that is neither in HEAD nor in the index.  Nothing
   happens.  This is the "untracked files" case.

The third case may smell that Git is discarding more than it needs
to, and if we were designing Git without any existing users from
scratch today, we might have chosen to remove it from the index and
make the working tree copy simply "untracked", but we already have
more than a dozen users that rely on the current behaviour, so such
a change is not likely to happen.

The biggest use of the third case is to abort a failed merge and to
restart it from scratch.  A path that is not in your branch that the
other branch created since the two branches forked will be added to
the index and to the working tree.  You see conflicts in other paths
(where both branches made changes in different and incompatible
ways), and after looking at it trying to resolve them, realize that
you made a mess and you want to start from scratch, i.e. you run
"reset --hard" followed by the same "git merge".

If "reset --hard" does not remove the "new" file from the index and
the working tree, the next "git merge" will think that the untracked
file is something you may have created, and would refuse to run, so
that it won't lose information.

As "reset --hard" is an operation that is run by the user to discard
the changes, it is understood to deliberately lose information, so
making the third one to remove the path from the working tree
(instead of making it untracked) is a better solution than forcing
the user in the "reset --hard && merge" scenario to see a merge that
does not even start (as opposed to "an attempted merge that resulted
in conflicts) and to manually remove these untracked files that the
user did not even create herself.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2016-05-23  0:55 Git reset --hard with staged changes Yotam Gingold
  2016-05-23 17:05 ` Junio C Hamano
@ 2016-05-23 19:31 ` Christian Couder
  2016-05-23 21:16   ` Junio C Hamano
  1 sibling, 1 reply; 17+ messages in thread
From: Christian Couder @ 2016-05-23 19:31 UTC (permalink / raw)
  To: Yotam Gingold; +Cc: git

On Mon, May 23, 2016 at 2:55 AM, Yotam Gingold <yotam@yotamgingold.com> wrote:
> Pierre-François CLEMENT <likeyn <at> gmail.com> writes:
>> 2014-06-10 17:27 GMT+02:00 David Kastrup <dak <at> gnu.org>:
>>> Pierre-François CLEMENT <likeyn <at> gmail.com> writes:
>>>
>>>> ...
>>>>
>>>> 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
>>
>> ... 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
>
> Jumping into this conversation two years later*. There's confusion about what
> constitutes a tracked file for git reset --hard, and good reasons for git reset
> --hard's behavior. Nevertheless, I think we can all agree that the man page
> entry for git reset --hard is woefully deficient:
>
> --hard Resets the index and working tree. Any changes to tracked files in the
> working tree since <commit> are discarded.
>
> This should be clarified to define what a tracked file is. I propose appending:
>
>     A file is considered tracked if it exists in a prior commit or in the
>     staging area. Note that a newly added file not in any prior commit will be
>     removed.

Would you like to send a patch with something like the above?

I don't know if something about why it is like this, or why it is the
right thing to do, at least for recovering from merges, should be
added though.

> I would also like to propose that the staging area's tree object be saved,
> perhaps in the reflog or perhaps just as a dangling object. This would allow
> graceful recovery from git reset --hard. Witness the many questions and answers
> on recovery:
>     http://stackoverflow.com/questions/7374069/undo-git-reset-hard-with-uncommitted-files-in-the-
> staging-area
>     http://stackoverflow.com/questions/5788037/recover-from-git-reset-hard
>     http://stackoverflow.com/questions/5473/how-can-i-undo-git-reset-hard-head1
>     http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html
>     https://bani.com.br/2014/10/recovering-lost-files-after-a-git-reset-hard/
>     https://medium.com/@CarrieGuss/how-to-recover-from-a-git-hard-reset-b830b5e3f60c
>
> All of these solutions recover the contents of files, but not their names or the
> directory structure. Saving the tree object somewhere (anywhere!) would solve
> this problem.

Yeah, it might be a good idea.

> I was bitten by this in a vicious way. I was setting up a new repository for a
> bunch of code and data (git init; git add .), changed my mind about adding the
> data (git reset --hard), and nearly lost everything.

I think we could also perhaps have a special case when the current
branch doesn't really exist yet.

At least if you had used "git reset --keep", it would have failed with:

$ git reset --keep
error: You do not have a valid HEAD.
fatal: Could not reset index file to revision 'HEAD'.

Also if there had already been a commit, with --keep the new files
would not have been deleted.

> The only tree object that
> could be found was an empty one, so I got file contents without names or
> directories (not good, because experimental conditions for the data were encoded
> in the directory structure).

Best,
Christian.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2016-05-23 19:31 ` Christian Couder
@ 2016-05-23 21:16   ` Junio C Hamano
  2016-05-24  6:20     ` Christian Couder
  0 siblings, 1 reply; 17+ messages in thread
From: Junio C Hamano @ 2016-05-23 21:16 UTC (permalink / raw)
  To: Christian Couder; +Cc: Yotam Gingold, git

Christian Couder <christian.couder@gmail.com> writes:

>> This should be clarified to define what a tracked file is. I propose appending:
>>
>>     A file is considered tracked if it exists in a prior commit or in the
>>     staging area. Note that a newly added file not in any prior commit will be
>>     removed.
>
> Would you like to send a patch with something like the above?

I am not sure if that is a good addition, though.

> I don't know if something about why it is like this, or why it is the
> right thing to do, at least for recovering from merges, should be
> added though.

I excuse you as it seems that you haven't read my response ;-)

>> I would also like to propose that the staging area's tree object be saved,
>> ..
> Yeah, it might be a good idea.

Two issues with that "proposal" is that

 1. the index may not be writable as a tree (think: during a
    conflict resolution); and

 2. the sole point of "reset --hard" is to "discard the changes".
    If you want to instead save them away, there is another command
    that was designed to do just that.

It wasn't all that surprising that those on stackoverflow would
think such a proposal is a good idea, but I somehow was hoping you
have been around here long enough to know "git stash" ;-)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2016-05-23 21:16   ` Junio C Hamano
@ 2016-05-24  6:20     ` Christian Couder
  2016-05-30  5:07       ` Yotam Gingold
  0 siblings, 1 reply; 17+ messages in thread
From: Christian Couder @ 2016-05-24  6:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Yotam Gingold, git

On Mon, May 23, 2016 at 11:16 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Christian Couder <christian.couder@gmail.com> writes:
>
>>> This should be clarified to define what a tracked file is. I propose appending:
>>>
>>>     A file is considered tracked if it exists in a prior commit or in the
>>>     staging area. Note that a newly added file not in any prior commit will be
>>>     removed.
>>
>> Would you like to send a patch with something like the above?
>
> I am not sure if that is a good addition, though.

I am not sure either, but at least if something like that is added,
people may complain less.

>> I don't know if something about why it is like this, or why it is the
>> right thing to do, at least for recovering from merges, should be
>> added though.
>
> I excuse you as it seems that you haven't read my response ;-)
>
>>> I would also like to propose that the staging area's tree object be saved,
>>> ..
>> Yeah, it might be a good idea.
>
> Two issues with that "proposal" is that
>
>  1. the index may not be writable as a tree (think: during a
>     conflict resolution); and
>
>  2. the sole point of "reset --hard" is to "discard the changes".
>     If you want to instead save them away, there is another command
>     that was designed to do just that.
>
> It wasn't all that surprising that those on stackoverflow would
> think such a proposal is a good idea, but I somehow was hoping you
> have been around here long enough to know "git stash" ;-)

Yeah, we can try to teach people about git stash and git reset --keep
instead, but I doubt that it will be very effective.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2016-05-24  6:20     ` Christian Couder
@ 2016-05-30  5:07       ` Yotam Gingold
  2016-05-31  6:02         ` Junio C Hamano
  0 siblings, 1 reply; 17+ messages in thread
From: Yotam Gingold @ 2016-05-30  5:07 UTC (permalink / raw)
  To: Christian Couder; +Cc: Junio C Hamano, git

> On May 24, 2016, at 2:20 AM, Christian Couder <christian.couder@gmail.com> wrote:
> 
> On Mon, May 23, 2016 at 11:16 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> 
>> 
>> I am not sure if that is a good addition, though.
> 
> I am not sure either, but at least if something like that is added,
> people may complain less.

The present documentation is at best wrong and at worst misleading.
I read Junio's enumerations of the situations, and I appreciate that the
current behavior of git reset --hard cannot be changed because of the
many tools that rely on the current behavior. After reading it, I have
modified my proposed amendment to the git reset --hard documentation:

    A file is considered tracked if it exists in a prior commit or in the
    staging area. Note that a newly added file not in any prior commit will be
    removed. This is useful for aborting a failed merge.

Shall I submit a patch?


>>>> I would also like to propose that the staging area's tree object be saved,
>>>> ..
>>> Yeah, it might be a good idea.
>> 
>> Two issues with that "proposal" is that
>> 
>> 1. the index may not be writable as a tree (think: during a
>>    conflict resolution); and

So why not do it only when possible? But in this case (and every case),
wouldn't a solution be to create a tree that is not the index just for the reflog?


>> 2. the sole point of "reset --hard" is to "discard the changes".
>>    If you want to instead save them away, there is another command
>>    that was designed to do just that.

git stash isn't relevant here. git reset --hard deletes data from disk that has
only ever been in the staging area. Many commands in git can be "undone"
due to the fact that it is a version control system and there is a reflog.
This is not one of those. git reset --hard can cause a catastrophic loss of
data, with no way to undo it.


>> It wasn't all that surprising that those on stackoverflow would
>> think such a proposal is a good idea, but I somehow was hoping you
>> have been around here long enough to know "git stash" ;-)
> 
> Yeah, we can try to teach people about git stash and git reset --keep
> instead, but I doubt that it will be very effective.

git stash doesn't make sense in this context. The documentation for
git reset --hard is misleading. The error is unrecoverable. How could anyone
but a git developer know this?

Yotam

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2016-05-30  5:07       ` Yotam Gingold
@ 2016-05-31  6:02         ` Junio C Hamano
  2016-05-31  6:41           ` Christian Couder
  0 siblings, 1 reply; 17+ messages in thread
From: Junio C Hamano @ 2016-05-31  6:02 UTC (permalink / raw)
  To: Yotam Gingold; +Cc: Christian Couder, git

Yotam Gingold <yotam@yotamgingold.com> writes:

> I read Junio's enumerations of the situations, and I appreciate that the
> current behavior of git reset --hard cannot be changed because of the
> many tools that rely on the current behavior. After reading it, I have
> modified my proposed amendment to the git reset --hard documentation:
>
>     A file is considered tracked if it exists in a prior commit or in the
>     staging area. Note that a newly added file not in any prior commit will be
>     removed. This is useful for aborting a failed merge.
>
> Shall I submit a patch?

I think the root cause of the confusion is that the description of
"reset --hard" uses an undefined word "tracked", which does not
appear anywhere else in "git reset --help".

A better rewrite is probably a one that does not to use such a fuzzy
word that is not even in official Git lingo (there is no glossary
entry for it).

 Documentation/git-reset.txt | 10 ++++++++--
 t/perf/perf-lib.sh          |  4 +++-
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index 25432d9..c4cc035 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -65,8 +65,14 @@ If `-N` is specified, removed paths are marked as intent-to-add (see
 linkgit:git-add[1]).
 
 --hard::
-	Resets the index and working tree. Any changes to tracked files in the
-	working tree since <commit> are discarded.
+	Reset the index and the working tree to be identical to the
+	tree of the given <commit> (defaults to HEAD) by discarding
+	the changes made to them relative to <commit>.  Paths
+	modified in the index and in the working tree are reset to
+	what is recorded in <commit>.  Paths removed in the working
+	tree and in the index are resurrected from <commit>.  Paths
+	added to the index and the working tree since <commit> are
+	removed.
 
 --merge::
 	Resets the index and updates the files in the working tree that are

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: Git reset --hard with staged changes
  2016-05-31  6:02         ` Junio C Hamano
@ 2016-05-31  6:41           ` Christian Couder
  0 siblings, 0 replies; 17+ messages in thread
From: Christian Couder @ 2016-05-31  6:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Yotam Gingold, git

On Tue, May 31, 2016 at 8:02 AM, Junio C Hamano <gitster@pobox.com> wrote:
>
> diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
> index 25432d9..c4cc035 100644
> --- a/Documentation/git-reset.txt
> +++ b/Documentation/git-reset.txt
> @@ -65,8 +65,14 @@ If `-N` is specified, removed paths are marked as intent-to-add (see
>  linkgit:git-add[1]).
>
>  --hard::
> -       Resets the index and working tree. Any changes to tracked files in the
> -       working tree since <commit> are discarded.
> +       Reset the index and the working tree to be identical to the
> +       tree of the given <commit> (defaults to HEAD) by discarding
> +       the changes made to them relative to <commit>.  Paths
> +       modified in the index and in the working tree are reset to
> +       what is recorded in <commit>.  Paths removed in the working
> +       tree and in the index are resurrected from <commit>.  Paths
> +       added to the index and the working tree since <commit> are
> +       removed.

This is a great improvement.

I am not sure that it will be enough to make people use `git stash`
and `git reset --keep` more though. But maybe that can wait until the
next time someone complain.

Thanks,
Christian.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2016-05-31  6:41 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-23  0:55 Git reset --hard with staged changes Yotam Gingold
2016-05-23 17:05 ` Junio C Hamano
2016-05-23 19:31 ` Christian Couder
2016-05-23 21:16   ` Junio C Hamano
2016-05-24  6:20     ` Christian Couder
2016-05-30  5:07       ` Yotam Gingold
2016-05-31  6:02         ` Junio C Hamano
2016-05-31  6:41           ` Christian Couder
     [not found] <CANWD=rWmzgAwTp=E_1=th0Myk-dh4m5Y9PE3=fpHeirsVVQKwQ@mail.gmail.com>
2014-06-09 11:24 ` Pierre-François CLEMENT
2014-06-09 14:04   ` David Kastrup
2014-06-09 23:22     ` Pierre-François CLEMENT
2014-06-09 23:28       ` Junio C Hamano
2014-06-10 14:59         ` Pierre-François CLEMENT
2014-06-10 15:27           ` David Kastrup
2014-06-10 16:30             ` Pierre-François CLEMENT
2014-06-10  1:03       ` Dale Worley
2014-06-10  5:44         ` Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).