Last active
November 23, 2021 09:34
-
-
Save brookinc/e2589a8c5ca33f804e4868f6bfc18282 to your computer and use it in GitHub Desktop.
A script to `git stash` only the currently staged changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# This script stashes the currently staged changes, and leaves everything else in the working directory as-is. | |
# (source: https://stackoverflow.com/questions/14759748/stashing-only-staged-changes-in-git-is-it-possible/39644782#39644782) | |
# Prompt for the desired repo path | |
REPOPATH= | |
read -p "Enter the repo path, or press ENTER for current dir: " REPOPATH | |
# Read the desired stash description from the command line, or prompt the user for it if necessary | |
STASHNAME=$1 | |
while [ "$STASHNAME" = "" ] ; do | |
read -p "Enter a description for this stash: " STASHNAME | |
done | |
#git -C "$REPOPATH" log -1 | |
# Stash everything temporarily. Keep staged files, discard everything else after stashing. | |
#git --git-dir $REPOPATH/.git stash --keep-index | |
git -C "$REPOPATH" stash --keep-index | |
# Stash everything that remains (only the staged files should remain). This is the stash we want to keep, so give it a name. | |
git -C "$REPOPATH" stash save "$STASHNAME" | |
# Apply the original stash to get us back to where we started | |
git -C "$REPOPATH" stash apply stash@{1} | |
# Create a temporary patch to reverse the originally staged changes and apply it | |
git -C "$REPOPATH" stash show -p | git -C "$REPOPATH" apply -R | |
# Delete the temporary stash | |
git -C "$REPOPATH" stash drop stash@{1} |
FYI - I needed a script that did something similarly: discard just the changes in the working dir:
( https://github.com/srgvg/dotfiles/blob/master/bin/git-undoworkingdir )
#!/bin/bash
# c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t
# vi: set shiftwidth=4 tabstop=4 noexpandtab:
# :indentSize=4:tabSize=4:noTabs=false:
set -o nounset
set -o errexit
set -o pipefail
# based on https://gist.github.com/brookinc/e2589a8c5ca33f804e4868f6bfc18282
# That original script stashes the currently staged changes, and leaves everything else in the working directory as-is.
# (source: https://stackoverflow.com/questions/14759748/stashing-only-staged-changes-in-git-is-it-possible/39644782#39644782)
# this script extends this as to basically throw away all unstaged changes
# and also makes referencing stashes more robust
function stashref() {
local stashname=$1
git stash list | grep "${stashname}" | head -n1 | cut -d: -f1
}
# Stash everything temporarily. Keep staged files, discard everything else after stashing.
git stash save --quiet --keep-index _tmp_all
# Stash everything that remains (only the staged files should remain). This is the stash we want to keep, so give it a name.
git stash save --quiet _tmp_index
# Apply the original stash to get us back to where we started, then drop that stash
git stash pop --quiet "$(stashref _tmp_all)"
# Create a temporary patch to reverse the stash with just the index and apply it
git stash show -p "$(stashref _tmp_index)" | git apply --index --reverse
# Now we have just the working dir changes without an index, and keep that stash as a backup of the real change here
TS="$(date +%H%M%S)"
git stash save "unstaged@${TS}" | sed 's/and index //'
git stash show -p "$(stashref unstaged@${TS})"
# Now re-apply the index, as index, then drop that stash
git stash pop --quiet --index "$(stashref _tmp_index)"
Good example! But I would rather like to add alias into .gitconfig like:
[alias]
stashstaged = !git stash --keep-index && \
git stash && \
git stash apply stash@{1} && \
git stash show -p | git apply -R && \
git stash drop stash@{1}
Thanks @typebrook that works great!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice script. Now you assume your first stach is stash@{1}, which might not always be true. I think i might be safer to also give a name to the first stash, and reference it when reverse applying, then dropping it. That would make your script more robust if there are already other stashes saved.