Это технически невозможно, но легко достичь желаемой цели с помощью обмана. Git просто не имеет встроенного механизма для выполнения хитрости, даже если git commit
имеет опцию --amend
, которая делает именно это. (Для этого также нет чистого способа угнать git commit --amend
.)
В конце концов, вы должны делать то, что предлагаете. Вы можете скрыть это в скрипте, если хотите, но для одноразового случая это больше, чем просто делать это вручную.
Технические подробности, если вы хотите создать скрипт
Под прикрытием команд и опций командной строки Git и т. Д. Запись Git stash на самом деле является коммитом. Точнее, это как минимум два коммита, а иногда три. Документация git stash
описывает это (довольно легко и небрежно) в разделе, обозначенном ОБСУЖДЕНИЕ. Особенность коммитов git stash
заключается в том, что они находятся на нет ветви - ну, что и что фиксация w
(рабочее дерево) в кластере, то есть та, которую находит ссылка refs/stash
, имеет форму фиксации слияния, так что она может перечислить несколько идентификаторов родительской фиксации. Я предпочитаю рисовать их так:
...--F--G <-- branch
|\
i-w <-- (the stash)
или
...--F--G <-- branch
|\
i-w <-- (the stash)
/
u
, который немного отличается от чертежа документации Git, но показывает, как то, что я называю шкатулкой (с необязательным u
коммитом, содержащим неотслеживаемые файлы), свисает с коммитом это было актуально, когда вы сделали тайник. (Если вы еще не переместили ваш HEAD
в другое место, этот коммит будет все еще текущего коммита.) Заглавные буквы здесь обозначают реальные хэши коммитов, которые большие и некрасивые и которые невозможно запомнить.
Как и во всех коммитах, специальные тайники являются только для чтения - их нельзя изменить, они могут забыть только свои хэш-идентификаторы (что делает git stash drop
).
Обратите внимание, что git commit --amend
фактически делает новый коммит, отодвигая текущий (HEAD) коммит в сторону. То есть, если мы начнем с:
...--F--G <-- branch (HEAD)
и запустите git commit --amend
, Git делает новый коммит - назовем это G2
- чей родитель F
, а не обычная идея использования G
в качестве G2
parent, затем записывает ID G2
в ветку, давая нам:
G
/
...--F--G2 <-- branch (HEAD)
До тех пор, пока старый коммит G
не имеет имени, по которому мы можем его найти, Git никогда не показывает его нам и в конечном итоге полностью его отбрасывает, создавая впечатление, будто мы каким-то образом изменили коммит G
на * 1060. *.
Чтобы существующая запись в stash имела другой комментарий о коммите, нам нужно было бы сделать то же самое: мы скопировали бы наш существующий w
коммит в новый коммит, с другим сообщением о коммите , но сохраните w
content и все его родительские хеши. Если мы позвоним на замену w2
, мы получим:
...--F--G_ <-- branch
|\`-.
i-w2 \
\ \
-----w <-- (the stash)
Если мы затем перенаправим refs/stash
, чтобы указать w2
вместо w
, и притворимся, что w
больше не существует, мы получим то, что хотим:
...--F--G <-- branch
|\
i-w2 <-- (the stash)
и фактически мы можем написать это как скрипт, начиная с следующих фрагментов кода:
# get the parents of refs/stash as $1 and $2; $3 exists if there is a u commit
set -- $(git rev-parse refs/stash^@)
# convert these to "-p $1 -p $2 -p $3"
case $# in
2) parents="-p $1 -p $2";;
3) parents="-p $1 -p $2 -p $3";;
*) fatal "refs/stash does not appear to be a valid stash";;
esac
# find the stashed w commit's tree
tree=$(git rev-parse refs/stash^{tree}) || exit
# optional: for editing purposes, gather the current message
existing_message=$(git log --no-walk --pretty=format:%B refs/stash)
# obtain an updated message in some fashion
[snip]
и затем:
# create a new w commit, suitable for "git stash store"
new_w_commit=$(git commit-tree $parents "$new_message" $tree)
и в конечном итоге:
git stash drop --quiet
git stash store --quiet -m "$new_message" $new_w_commit
, который использует сам скрипт git stash
для замены stash@{0}
новым тайником. (В случае прерывания может быть разумнее изменить порядок этих двух операций. Выяснение того, как сделать это с помощью ссылки stash@{n}
, оставлено в качестве упражнения. Ничего из этого даже не проверено дистанционно.)