Re: [FEATURE] Proposal: git stash --only-unstaged
From: Junio C Hamano <hidden>
Date: 2025-08-17 16:08:41
Phillip Wood [off-list ref] writes:
To use it create your stash with "git stash push --keep-index" and then use the script to pop the unstaged changes rather than using "git stash pop". If the script proves to be useful then perhaps we could add an "--unstaged" option to "git stash pop"
Hmph, would the behaviour useful enough that it should be always enabled, without any new option? I strongly suspect that those who worked on adding "--keep-index" option did not expect the user to be mucking with the working tree files while "testing the staged stuff by updating the working tree files to match it and nothing else", and as long as the end-user stays within that originally designed use case, nothing changes for them, no? Thanks. (the script left for reference without comments below).
---- 8< ----
#!/bin/sh
USAGE="${0##*/} [<stash>]"
SUBDIRECTORY_OK=1
. "$(git --exec-path)/git-sh-setup"
cd_to_toplevel
require_clean_work_tree stash-pop-unstaged
LF='
'
stash="${1:-stash@{0}}"
if ! stash_oid="$(git rev-parse --verify --quiet "$stash")" ||
! oid1="$(git rev-parse --verify --quiet $stash_oid^1)" ||
! oid2="$(git rev-parse $stash_oid^2^@ 2>/dev/null)" ||
test "$oid1" != "$oid2"
then
die "error: '$stash' does not look like a stash commit"
fi
merge_output="$(git merge-tree --merge-base=$stash_oid^2: HEAD: $stash_oid:)"
status=$?
if test $status = 0
then
tree=$merge_output
conflict_info=
messages=
elif test $status = 1
then
merge_output="$merge_output$LF"
tree="${merge_output%%$LF*}"
conflict_info="${merge_output%%$LF$LF*}"
conflict_info="${conflict_info#*$LF}"
messages="${merge_output#*$LF$LF}"
else
exit 128
fi
git read-tree --index-output="$GIT_DIR/stash-pop-index" -m -u HEAD $tree &&
rm "$GIT_DIR/stash-pop-index" &&
if test -n "$conflict_info"
then
printf '%s' "$messages" >&2
printf '%s\n' "$conflict_info" | git update-index --index-info
else
git stash drop "$stash"
fi