* [PATCH] Teach git-stash to "apply --index"
@ 2007-07-02 11:14 Johannes Schindelin
2007-07-03 4:33 ` Junio C Hamano
0 siblings, 1 reply; 3+ messages in thread
From: Johannes Schindelin @ 2007-07-02 11:14 UTC (permalink / raw)
To: git, gitster
When given this subcommand, git-stash will try to merge the stashed
index into the current one. Only trivial merges are possible, since
we have no index for the index ;-) If a trivial merge is not possible,
git-stash will bail out with a hint to skip the --index option.
For good measure, finally include a test case.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
I am not quite sure if this should not be the default, with
--skip-index to turn it off if the trivial index merge fails,
and the user might be interested only in the working directory
changes anyway.
Comments?
git-stash.sh | 21 ++++++++++++++++
t/t3903-stash.sh | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 89 insertions(+), 1 deletions(-)
diff --git a/git-stash.sh b/git-stash.sh
index 04ce30a..45ad2f4 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -98,6 +98,13 @@ apply_stash () {
git-diff-files --quiet ||
die 'Cannot restore on top of a dirty state'
+ unstash_index=
+ case "$1" in
+ --index)
+ unstash_index=t
+ shift
+ esac
+
# current index state
c_tree=$(git-write-tree) ||
die 'Cannot apply a stash in the middle of a merge'
@@ -107,6 +114,15 @@ apply_stash () {
b_tree=$(git-rev-parse --verify "$s^:") ||
die "$*: no valid stashed state found"
+ test -z "$unstash_index" || {
+ git diff --binary $s^2^..$s^2 | git apply --cached
+ test $? -ne 0 &&
+ die 'Conflicts in index. Try without --index.'
+ unstashed_index_tree=$(git-write-tree) ||
+ die 'Could not save index tree'
+ git reset
+ }
+
eval "
GITHEAD_$w_tree='Stashed changes' &&
GITHEAD_$c_tree='Updated upstream' &&
@@ -124,9 +140,12 @@ apply_stash () {
die "Cannot unstage modified files"
git-status
rm -f "$a"
+ test -z "$unstash_index" || git read-tree $unstashed_index_tree
else
# Merge conflict; keep the exit status from merge-recursive
- exit
+ status=$?
+ test -z "$unstash_index" || echo 'Index was not unstashed.' >&2
+ exit $status
fi
}
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
new file mode 100755
index 0000000..392ac1c
--- /dev/null
+++ b/t/t3903-stash.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E Schindelin
+#
+
+test_description='Test git-stash'
+
+. ./test-lib.sh
+
+test_expect_success 'stash some dirty working directory' '
+ echo 1 > file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ echo 2 > file &&
+ git add file &&
+ echo 3 > file &&
+ test_tick &&
+ git stash &&
+ git diff-files --quiet &&
+ git diff-index --cached --quiet HEAD
+'
+
+cat > expect << EOF
+diff --git a/file b/file
+index 0cfbf08..00750ed 100644
+--- a/file
++++ b/file
+@@ -1 +1 @@
+-2
++3
+EOF
+
+test_expect_success 'parents of stash' '
+ test $(git rev-parse stash^) = $(git rev-parse HEAD) &&
+ git diff stash^2..stash > output &&
+ diff -u output expect
+'
+
+test_expect_success 'apply needs clean working directory' '
+ echo 4 > other-file &&
+ git add other-file &&
+ echo 5 > other-file
+ ! git stash apply
+'
+
+test_expect_success 'apply stashed changes' '
+ git add other-file &&
+ test_tick &&
+ git commit -m other-file &&
+ git stash apply &&
+ test 3 = $(cat file) &&
+ test 1 = $(git show :file) &&
+ test 1 = $(git show HEAD:file)
+'
+
+test_expect_success 'apply stashed changes (including index)' '
+ git reset --hard HEAD^ &&
+ echo 6 > other-file &&
+ git add other-file &&
+ test_tick &&
+ git commit -m other-file &&
+ git stash apply --index &&
+ test 3 = $(cat file) &&
+ test 2 = $(git show :file) &&
+ test 1 = $(git show HEAD:file)
+'
+
+test_done
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] Teach git-stash to "apply --index"
2007-07-02 11:14 [PATCH] Teach git-stash to "apply --index" Johannes Schindelin
@ 2007-07-03 4:33 ` Junio C Hamano
2007-07-03 11:17 ` Johannes Schindelin
0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2007-07-03 4:33 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> I am not quite sure if this should not be the default, with
> --skip-index to turn it off if the trivial index merge fails,
> and the user might be interested only in the working directory
> changes anyway.
>
> Comments?
There is a bit of impedance mismatch between a rename-aware
three-way merge (aka merge-recursive) used to update the working
tree and a patch that updates the index. The "rename-aware"
thing can be fixed by doing the diff with -M, though.
It might be easier to explain (1) not have --index option, but
attempt to do this always, and (2) even if the index cannot be
updated, keep going, without worrying about losing the
difference between I and W, probably with a message to the end
user.
Suppose you are the user who gets "perhaps you would want to run
without --index?" hint. What can you do? Run without --index,
or forget about unstashing. But the latter does not sound like
an option. So it feels to me that --index is an unnecessary
option.
The potential confusion problem I mentioned in two of my earlier
messages due to the program doing one thing sometimes and
another thing some other times still applies, though.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Teach git-stash to "apply --index"
2007-07-03 4:33 ` Junio C Hamano
@ 2007-07-03 11:17 ` Johannes Schindelin
0 siblings, 0 replies; 3+ messages in thread
From: Johannes Schindelin @ 2007-07-03 11:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Mon, 2 Jul 2007, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > I am not quite sure if this should not be the default, with
> > --skip-index to turn it off if the trivial index merge fails,
> > and the user might be interested only in the working directory
> > changes anyway.
> >
> > Comments?
>
> There is a bit of impedance mismatch between a rename-aware
> three-way merge (aka merge-recursive) used to update the working
> tree and a patch that updates the index. The "rename-aware"
> thing can be fixed by doing the diff with -M, though.
Ah yes, I did not think about renames. But like you said, adding -M to the
diff should help that.
> It might be easier to explain (1) not have --index option, but attempt
> to do this always, and (2) even if the index cannot be updated, keep
> going, without worrying about losing the difference between I and W,
> probably with a message to the end user.
Okay, in this case I propose to make this the default, with an option
"--skip-index" to only try re-apply the changes to the working directory.
> Suppose you are the user who gets "perhaps you would want to run without
> --index?" hint. What can you do? Run without --index, or forget about
> unstashing. But the latter does not sound like an option. So it feels
> to me that --index is an unnecessary option.
It is very much like the choice you have with "git checkout" vs "git
checkout -f". Either you change your index accordingly, or you say "I
don't care about the index. What changes I had there, I will reconstruct
myself."
> The potential confusion problem I mentioned in two of my earlier
> messages due to the program doing one thing sometimes and another thing
> some other times still applies, though.
Yes, that's why I would suggest not going ahead when the index could not
be easily merged. Rather give the user enough information to decide.
Of course, this means that in complicated cases, the user mustn't run and
hide when she hears "index!", but I guess that complicated cases always
need you to know your tools better than easy problems.
Ciao,
Dscho
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2007-07-03 11:17 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-02 11:14 [PATCH] Teach git-stash to "apply --index" Johannes Schindelin
2007-07-03 4:33 ` Junio C Hamano
2007-07-03 11:17 ` Johannes Schindelin
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).