git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Phillip Wood <phillip.wood123@gmail.com>
To: "J. Dettweiler" <git.vger.kernel.org@dettweb.de>, git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>,
	"D. Ben Knoble" <ben.knoble@gmail.com>
Subject: Re: [FEATURE] Proposal: git stash --only-unstaged
Date: Sat, 16 Aug 2025 17:12:47 +0100	[thread overview]
Message-ID: <60f38225-2bcb-4383-be40-36c7b02cf38c@gmail.com> (raw)
In-Reply-To: <12fe17735317215aa0de58a20055193a@dettweb.de>

On 13/08/2025 09:51, J. Dettweiler wrote:
> 
> **Current limitations:**
> - `git stash --keep-index` still saves the index in the stash object.
> - When I later `git stash pop`, Git tries to restore those staged 
> changes, often causing merge conflicts if I’ve modified them during the 
> test.

As the index and the worktree are saved in the stash we can restore the
unstaged changes with a three-way merge between the stashed index, HEAD
and the stashed worktree. The (lightly tested) script below does that
and updates the worktree without changing the index unless there are
conflicts. There will only be conflicts when a staged line that is
adjacent to an unstaged line is changed. Changes to staged lines that
are not next to unstaged lines should not create conflicts as they are
only modified on one side of the merge.

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"

Thanks

Phillip

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


  parent reply	other threads:[~2025-08-16 16:12 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-13  8:51 [FEATURE] Proposal: git stash --only-unstaged J. Dettweiler
2025-08-13 15:30 ` Junio C Hamano
2025-08-13 17:02 ` D. Ben Knoble
2025-08-16 16:12 ` Phillip Wood [this message]
2025-08-17 16:08   ` Junio C Hamano
2025-08-18 15:14     ` Phillip Wood
2025-08-18 23:41       ` Ben Knoble
2025-08-29 13:06         ` Phillip Wood
2025-08-29 13:30           ` D. Ben Knoble
2025-09-16 11:03             ` Phillip Wood
2025-09-16 17:10               ` D. Ben Knoble

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=60f38225-2bcb-4383-be40-36c7b02cf38c@gmail.com \
    --to=phillip.wood123@gmail.com \
    --cc=ben.knoble@gmail.com \
    --cc=git.vger.kernel.org@dettweb.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=phillip.wood@dunelm.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).