63

作業ツリーを変更せずにスタッシュを保存する git コマンドを使用したいと思っていました。これは、git のリセットや、インデックスを台無しにするために行う可能性のあることから安全な軽量のバックアップとしてです。基本的に、「git stash save && git stash apply」と同等の機能を果たしますが、特定のテキスト エディター/IDE が不機嫌になる可能性があるため、作業コピーがまったく変更されない点が異なります。

このようなものは私が望むものに近づいていますが、完全ではありません:

git update-ref refs/stash `git stash create "Stash message"`

これは機能的には機能しますが、実際の stash コミットにはメッセージが含まれているにもかかわらず、「git stash list」に stash メッセージが表示されないという問題があります。stash のサイズを考えると、stash メッセージは非常に重要です。

4

5 に答える 5

35

Charles のヒントのおかげで、私は自分のやりたいことを正確に実行できるように bash スクリプトを作成しました (これを単なるエイリアスとして実装する際に問題が発生していました)。git stash save と同様に、オプションの stash メッセージを受け取ります。何も指定されていない場合は、git stash によって生成されたデフォルトのメッセージが使用されます。

#!/bin/sh
#
# git-stash-snap
# Save snapshot of working tree into the stash without modifying working tree.
# First argument (optional) is the stash message.
if [ -n "$1" ]; then
        git update-ref -m "$1" refs/stash "$(git stash create \"$1\")"
else
        HASH=`git stash create`
        MESSAGE=`git log --no-walk --pretty="tformat:%-s" "$HASH"`
        git update-ref -m "$MESSAGE" refs/stash "$HASH"
fi

編集:以下のコメントで指摘されているように、このスクリプトをgit-stash-snapパスのどこかに保存するだけで、入力して呼び出すことができますgit stash-snap

ここでの素晴らしい点は、この方法で作成された stash をドロップしても、ぶら下がっているコミットの git log [commit-hash] を使用して stash メッセージを表示できることです!

編集: git 2.6.0 以降に追加--create-reflogするupdate-refと、以前に使用されていなかったgit stash list場合でもこれが表示されます。git stash

編集: Git は と呼ばれる新しい stash サブコマンドを導入したstash pushため、このスクリプトの命名に関する推奨事項を から に更新しgit-stash-pushましたgit-stash-snap

于 2011-06-11T21:13:13.007 に答える
14

update-refではなくstash create、メッセージを に渡す必要がありstash createます (ref を更新しないため、入力する reflog エントリがありません)。

git update-ref -m "Stash message" refs/stash "$(git stash create)"
于 2011-06-11T11:11:21.623 に答える
6

Eliot のソリューションに触発されて、私は彼のスクリプトを少し拡張しました。

#!/bin/sh
#
# git-stash-push
# Push working tree onto the stash without modifying working tree.
# First argument (optional) is the stash message.
#
# If the working dir is clean, no stash will be generated/saved.
#
# Options:
#   -c "changes" mode, do not stash if there are no changes since the
#      last stash.
if [ "$1" == "-c" ]; then
        CHECK_CHANGES=1
        shift
fi


if [ -n "$1" ]; then
        MESSAGE=$1
        HASH=$( git stash create "$MESSAGE" )
else
        MESSAGE=`git log --no-walk --pretty="tformat:%-s" "HEAD"`
        MESSAGE="Based on: $MESSAGE"
        HASH=$( git stash create )
fi

if [ "$CHECK_CHANGES" ]; then
        # "check for changes" mode: only stash if there are changes
        # since the last stash

        # check if nothing has changed since last stash
        CHANGES=$( git diff stash@{0} )
        if [ -z "$CHANGES" ] ; then
                echo "Nothing changed since last stash."
                exit 0
        fi
fi

if [ -n "$HASH" ]; then
        git update-ref -m "$MESSAGE" refs/stash "$HASH"
        echo "Working directory stashed."
else
        echo "Working tree clean, nothing to do."
fi

エリオットのスクリプトに次の変更を実装しました。

  1. 作業ディレクトリがクリーンになると、スクリプトは正常に終了します
  2. switch-cが使用されている場合、最後の stash と比較して変更がない場合、スクリプトは終了します。これは、このスクリプトを「タイム マシン」として使用し、10 分ごとに自動化された stash を作成する場合に便利です。何も変更されていない場合、新しい stash は作成されません。このスイッチがないと、n 回連続して同じ stash が作成される可能性があります。

スイッチ-cが正しく機能するためには、少なくとも 1 つの stash が存在する必要があります。存在しない場合、スクリプトはエラーをスローし、git diff stash@{0}何もしません。

このスクリプトを「タイム マシン」として使用し、次の bash ループを使用して 10 分ごとにスナップショットを作成します。

 while true ; do date ; git stash-push ; sleep 600 ; done
于 2016-03-09T12:29:49.107 に答える