Re: Better cooperation between checkouts and stashing

4 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: Better cooperation between checkouts and stashing

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:22

Michael Witten [off-list ref] writes:
..., I think you essentially want to implement
"git checkout" with something like the following (this hack is **not**
meant as a solution; it is only meant to illustrate what I think is
Markus Elfring's desire):
Your "checkout" needs a bit better error checking.  For example, you don't
want to "reset --hard" when stash failed for whatever reason.

For performance and cleanliness reasons, it should first try a branch
switch, and only after seeing it fail due to local changes, perform your
stash-unstash magic.  You would probably want to use the usual "stash
save", as you will be consuming the stashed change yourself as its first
user, and "pop" will clear it if things resolve cleanly, or the stash will
be left as the first element to make it easy to re-attempt the conflict
resolution.  No need for stash-id nor special casing of detached HEAD
situation.

And it should do all that only under "-m" option, i.e. when the user
indicated that s/he is willilng to face conflict resolution while
switching.  That would be a genuine improvement compared to the current
system (and I suspect it would be easier to implement).  "checkout -m" so
far has been as bad as "CVS/SVN update" in that it can get you into an
unresolvable mess without a chance to go back and retry.  autostash will
remedy that.

Re: Better cooperation between checkouts and stashing

From: Michael Witten <hidden>
Date: 2016-06-15 22:48:22

On Mon, Mar 1, 2010 at 11:23, Junio C Hamano [off-list ref] wrote:
Your "checkout" needs a bit better error checking.  For example, you
don't want to "reset --hard" when stash failed for whatever reason.
Yes, you are correct.

However, in my defense, the goal was just to illustrate the gist
of the desired functionality.
For performance and cleanliness reasons, it should first try a branch
switch, and only after seeing it fail due to local changes, perform your
stash-unstash magic.  You would probably want to use the usual "stash
save", as you will be consuming the stashed change yourself as its first
user, and "pop" will clear it if things resolve cleanly, or the stash will
be left as the first element to make it easy to re-attempt the conflict
resolution.  No need for stash-id nor special casing of detached HEAD
situation.

And it should do all that only under "-m" option, i.e. when the user
indicated that s/he is willilng to face conflict resolution while
switching.  That would be a genuine improvement compared to the current
system (and I suspect it would be easier to implement).  "checkout -m" so
far has been as bad as "CVS/SVN update" in that it can get you into an
unresolvable mess without a chance to go back and retry.  autostash will
remedy that.
You've still got the wrong problem in your head (though you're
solving a more useful issue).

Markus Elfring's goal (I think) is to associate local modifications with
a particular branch, *not* carry them across branches; that is, the goal
is to stash local modifications away when we leave a branch and only pop
them off the stash when we RETURN to that same branch.

Here's an example using the previously defined custom `checkout' function
(don't bother trying to follow the file modifications exactly; what's
important is how the stash is used during `checkout'):

  $ git init repo
  Initialized empty Git repository in /home/michael/repo/.git/


  $ cd repo
  $ echo 0 > file_0
  $ git add file_0
  $ git commit -m 0
  [master (root-commit) 26ea762] 0
   1 files changed, 1 insertions(+), 0 deletions(-)
   create mode 100644 file_0


  $ echo 1 > file_1
  $ git add file_1
  $ git commit -m 1
  [master 2faaa55] 1
   1 files changed, 1 insertions(+), 0 deletions(-)
   create mode 100644 file_1


  $ echo 2 > file_0
  $ echo 3 > file_1
  $ git add file_1


  $ git branch branch
  $ checkout branch               # Note: That's the custom 'checkout'
  Switched to branch 'branch'


  $ git stash list | cat
  stash@{0}: On master: e2f0bfbd9de98acd4941a1842e4bc55f


  $ echo 4 > file_0
  $ checkout HEAD^
  Note: checking out 'HEAD^'.
  
  You are in 'detached HEAD' state. You can look around, make experimental
  changes and commit them, and you can discard any commits you make in this
  state without impacting any branches by performing another checkout.
  
  If you want to create a new branch to retain commits you create, you may
  do so (now or later) by using -b with the checkout command again. Example:
  
    git checkout -b new_branch_name
  
  HEAD is now at 26ea762... 0


  $ git stash list | cat
  stash@{0}: On branch: 3e4d8fe5cbdcf73b9272ad21b4510424
  stash@{1}: On master: e2f0bfbd9de98acd4941a1842e4bc55f


  $ echo 5 > file_0 


  $ checkout master
  HEAD is now at 26ea762 0
  Previous HEAD position was 26ea762... 0
  Switched to branch 'master'
  # On branch master
  # Changes to be committed:
  #   (use "git reset HEAD <file>..." to unstage)
  #
  #	modified:   file_1
  #
  # Changed but not updated:
  #   (use "git add <file>..." to update what will be committed)
  #   (use "git checkout -- <file>..." to discard changes in working directory)
  #
  #	modified:   file_0
  #
  Dropped stash@{1} (6871afd660a5814a1caffe5275a9c145dba3c85a)


  $ git stash list | cat
  stash@{0}: On branch: 3e4d8fe5cbdcf73b9272ad21b4510424


  $ checkout branch
  Switched to branch 'branch'
  # On branch branch
  # Changed but not updated:
  #   (use "git add <file>..." to update what will be committed)
  #   (use "git checkout -- <file>..." to discard changes in working directory)
  #
  #	modified:   file_0
  #
  no changes added to commit (use "git add" and/or "git commit -a")
  Dropped stash@{1} (f6ecf1ceed97c760cb2b3279bbb39fc1cd16f052)


  $ git stash list | cat
  stash@{0}: On master: e2f0bfbd9de98acd4941a1842e4bc55f


  $ checkout master
  Switched to branch 'master'
  # On branch master
  # Changes to be committed:
  #   (use "git reset HEAD <file>..." to unstage)
  #
  #	modified:   file_1
  #
  # Changed but not updated:
  #   (use "git add <file>..." to update what will be committed)
  #   (use "git checkout -- <file>..." to discard changes in working directory)
  #
  #	modified:   file_0
  #
  Dropped stash@{1} (46a64d63441a924d9684c8a733a9fae4c7aa4b92)


  $ git stash list | cat
  stash@{0}: On branch: 3e4d8fe5cbdcf73b9272ad21b4510424

  $ git diff | cat
  diff --git a/file_0 b/file_0
  index 573541a..0cfbf08 100644
  --- a/file_0
  +++ b/file_0
  @@ -1 +1 @@
  -0
  +2

  $ git diff --staged | cat
  diff --git a/file_1 b/file_1
  index d00491f..00750ed 100644
  --- a/file_1
  +++ b/file_1
  @@ -1 +1 @@
  -1
  +3

etc.

Re: Better cooperation between checkouts and stashing

From: Markus Elfring <hidden>
Date: 2016-06-15 22:48:22

Markus Elfring's goal (I think) is to associate local modifications with
a particular branch, *not* carry them across branches; that is, the goal
is to stash local modifications away when we leave a branch and only pop
them off the stash when we RETURN to that same branch.
You are right. - I am especially interested in this use case.

I would like to stress the relationships of files for a specific software
development task

Regards,
Markus

Re: Better cooperation between checkouts and stashing

From: Markus Elfring <hidden>
Date: 2016-06-15 22:48:22

You've still got the wrong problem in your head (though you're
solving a more useful issue).
Which idea would be better?

Regards,
Markus
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help