git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Stash does not save rename information
@ 2019-12-14 19:41 Chrissy Wainwright
  2019-12-14 23:00 ` Kyle Meyer
  0 siblings, 1 reply; 6+ messages in thread
From: Chrissy Wainwright @ 2019-12-14 19:41 UTC (permalink / raw)
  To: git

This seems to be a bug:
 
	1	Use `git mv` to rename a file
	2	`git status` shows the file was renamed
	3	Stash the changes
	4	Pop the stash
	5	`git status` shows the file change as deleted/new file instead of a rename


Thanks
Chrissy Wainwright
 
-- 
Six Feet Up, Inc.
Python & Cloud Expert Consulting 
Direct Line: +1 (317) 861-5948 x(604)
Email: chrissy@sixfeetup.com
https://sixfeetup.com
 


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

* Re: Stash does not save rename information
  2019-12-14 19:41 Stash does not save rename information Chrissy Wainwright
@ 2019-12-14 23:00 ` Kyle Meyer
  2019-12-14 23:05   ` Kyle Meyer
  0 siblings, 1 reply; 6+ messages in thread
From: Kyle Meyer @ 2019-12-14 23:00 UTC (permalink / raw)
  To: Chrissy Wainwright, git

Chrissy Wainwright <chrissy@sixfeetup.com> writes:

> This seems to be a bug:
>  
> 	1	Use `git mv` to rename a file
> 	2	`git status` shows the file was renamed
> 	3	Stash the changes
> 	4	Pop the stash
> 	5	`git status` shows the file change as deleted/new file instead of a rename

You can see very similar behavior with just a deleted file rather than a
deleted/new file pair (which is displayed as a rename depending on your
configuration):

    $ git init
    $ touch foo && git add foo && git commit -mfoo
    $ git stash
    $ git stash apply
    Removing foo
    On branch master
    Changes not staged for commit:
    	    deleted:    foo

    no changes added to commit

I believe the key thing is that by default 'git stash {apply,pop}' will
apply your change to the working tree but not the index [*].  If you
pass the --index flag, you should see the behavior you're after:

    $ git reset --hard
    HEAD is now at c023af6 foo
    $ git stash apply --index
    Removing foo
    On branch master
    Changes to be committed:
    	    deleted:    foo


[*] When I initially tried your example, I was confused that the new
    file was added to the index by default, but it seems new files
    receive special treatment, as Jeff King mentions at
    https://lore.kernel.org/git/20161206142446.5ba3wc625p5o6nct@sigill.intra.peff.net/

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

* Re: Stash does not save rename information
  2019-12-14 23:00 ` Kyle Meyer
@ 2019-12-14 23:05   ` Kyle Meyer
  2019-12-16 14:32     ` Chrissy Wainwright
  0 siblings, 1 reply; 6+ messages in thread
From: Kyle Meyer @ 2019-12-14 23:05 UTC (permalink / raw)
  To: Chrissy Wainwright, git

Kyle Meyer <kyle@kyleam.com> writes:
>
>     $ git init
>     $ touch foo && git add foo && git commit -mfoo

Sorry, I forgot to paste in the `git rm foo` step here.

>     $ git stash
>     $ git stash apply
>     Removing foo
>     On branch master
>     Changes not staged for commit:
>     	    deleted:    foo
>
>     no changes added to commit

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

* Re: Stash does not save rename information
  2019-12-14 23:05   ` Kyle Meyer
@ 2019-12-16 14:32     ` Chrissy Wainwright
  2019-12-16 18:42       ` Bryan Turner
  2019-12-16 19:25       ` Jeff King
  0 siblings, 2 replies; 6+ messages in thread
From: Chrissy Wainwright @ 2019-12-16 14:32 UTC (permalink / raw)
  To: Kyle Meyer, git

Thank you, using --index does work! Now the trick is to actually remember to use it in this case, since it doesn't seem the change can be restored if you forget to use it the first time you pop/apply.

Then the fix is to `git mv` the files back to the original name, and to the new name again.

Thanks
Chrissy Wainwright
 
-- 
Six Feet Up, Inc.
Python & Cloud Expert Consulting 
Direct Line: +1 (317) 861-5948 x(604)
Email: chrissy@sixfeetup.com
https://sixfeetup.com
 

On 12/14/19, 5:05 PM, "Kyle Meyer" <kyle@kyleam.com> wrote:

    Kyle Meyer <kyle@kyleam.com> writes:
    >
    >     $ git init
    >     $ touch foo && git add foo && git commit -mfoo
    
    Sorry, I forgot to paste in the `git rm foo` step here.
    
    >     $ git stash
    >     $ git stash apply
    >     Removing foo
    >     On branch master
    >     Changes not staged for commit:
    >     	    deleted:    foo
    >
    >     no changes added to commit
    


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

* Re: Stash does not save rename information
  2019-12-16 14:32     ` Chrissy Wainwright
@ 2019-12-16 18:42       ` Bryan Turner
  2019-12-16 19:25       ` Jeff King
  1 sibling, 0 replies; 6+ messages in thread
From: Bryan Turner @ 2019-12-16 18:42 UTC (permalink / raw)
  To: Chrissy Wainwright; +Cc: Kyle Meyer, git

On Mon, Dec 16, 2019 at 6:32 AM Chrissy Wainwright
<chrissy@sixfeetup.com> wrote:
>
> Thank you, using --index does work! Now the trick is to actually remember to use it in this case, since it doesn't seem the change can be restored if you forget to use it the first time you pop/apply.

You could create a Git alias for it, if that helps.

>
> Then the fix is to `git mv` the files back to the original name, and to the new name again.

That shouldn't be necessary. Really all you need to do is stage the
parts of the change that "git stash apply" didn't automatically stage
as part of restoring them. "git add -a" would likely do it, but may
also stage other things. A simple "git add foo" (based on the names
from your example) should also do it:

$ git init foo
Initialized empty Git repository in /.../foo/.git/
$ cd foo
$ touch foo && git add foo && git commit -m "Initial commit"
[master (root-commit) 934d270] Initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 foo
$ git mv foo bar
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    foo -> bar

$ git stash
Saved working directory and index state WIP on master: 934d270 Initial commit
$ git stash apply
Removing foo
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   bar

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    deleted:    foo

$ git add foo
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    foo -> bar

On some older versions of Git you may need to use "git add -f foo" to
add the deleted file, but at least on 2.20.1, what I happen to be
running locally, it's not necessary.

With or without "-f", all you really need to do is update what parts
of the change are staged; you don't need to (essentially) revert and
reapply the change.

One other thing I think may be worth clarifying, just in case it's not
know, is in relation to the subject: "Stash does not save rename
information." Git itself does not track renames, at all, in any
commands. git mv does not somehow record renames; it's just a
simplification for:
mv foo bar
git rm foo # or git add foo to stage the deletion
git add bar

You can confirm that easily:
$ git reset --hard HEAD
HEAD is now at 934d270 Initial commit
$ mv foo bar
$ git rm foo
rm 'foo'
$ git add bar
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    foo -> bar

$ git reset --hard HEAD
HEAD is now at 934d270 Initial commit
Lafiel:foo bturner$ mv foo bar
Lafiel:foo bturner$ git add foo bar
Lafiel:foo bturner$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    foo -> bar

Git uses heuristics to "pair up" deletions and adds into probable
renames. If you rename a file and change it significantly as part of
the same commit, Git will not consider it a rename. Similarly, if you
rename multiple similar files in a single commit, paired with some
changes to those files, Git may pair up the "wrong" combinations (i.e.
if you rename A to X and B to Y, "git diff" may show renaming A to Y
and B to X).

Hope this helps,
Bryan Turner

>
> Thanks
> Chrissy Wainwright

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

* Re: Stash does not save rename information
  2019-12-16 14:32     ` Chrissy Wainwright
  2019-12-16 18:42       ` Bryan Turner
@ 2019-12-16 19:25       ` Jeff King
  1 sibling, 0 replies; 6+ messages in thread
From: Jeff King @ 2019-12-16 19:25 UTC (permalink / raw)
  To: Chrissy Wainwright; +Cc: Kyle Meyer, git

On Mon, Dec 16, 2019 at 02:32:31PM +0000, Chrissy Wainwright wrote:

> Thank you, using --index does work! Now the trick is to actually
> remember to use it in this case, since it doesn't seem the change can
> be restored if you forget to use it the first time you pop/apply.

I think this is a spot where git-stash could be a little friendlier. If
you've stashed index changes and "git stash pop", then those index
changes are not applied but get thrown away, losing information.

It would be nicer if "stash pop" noticed that there are entries in the
stashed index that do not match HEAD or the stashed working tree, and
applied as requested but _didn't_ remove the stash (with a message that
you can get your index changes out with "--keep-index").

Maybe a good small project for somebody looking to get their feet wet
with contributing to Git (you, or anybody else reading this).

-Peff

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

end of thread, other threads:[~2019-12-16 19:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-14 19:41 Stash does not save rename information Chrissy Wainwright
2019-12-14 23:00 ` Kyle Meyer
2019-12-14 23:05   ` Kyle Meyer
2019-12-16 14:32     ` Chrissy Wainwright
2019-12-16 18:42       ` Bryan Turner
2019-12-16 19:25       ` Jeff King

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).