Parfois, je pouvais utiliser un équivalent de git stash && git checkout $branch && git stash pop
qui se souviendrait de l'état de l'arbre pour une branche donnée et ne restituerait que celui qui était caché pour cette branche particulière. Comment pourrait facilement réaliser cela?basculer entre les branches, en préservant la cachette?
Répondre
De par sa conception, git stash
fait un commettras temporaire qui ne sont pas sur une branche. C'est ainsi que vous pouvez l'appliquer n'importe où ailleurs.
Si vous souhaitez enregistrer l'état de l'index et/ou de l'arborescence et associer cet état à une branche particulière, ce que Git fournit est git commit
. Vraiment, c'est tout ce dont vous avez besoin: un vieux commit régulier. Vous pouvez "décommander" plus tard, une fois que vous revenez à cette branche, avec git reset --soft HEAD^
. Si vous souhaitez envelopper ce paquet dans un seul paquet, vous pouvez choisir un court message de commit que vous promettez de ne jamais utiliser dans un commit "réel", et écrire un petit wrapper pour git checkout
(note, ceci n'est pas testé) :
#! /bin/sh
# git-swapto: commit any temporary work, swap to another branch;
# automatically de-commits temporary work.
# for git-sh-setup: can work in subdirectory
SUBDIRECTORY_OK=true
. $(git --exec-path)/git-sh-setup
case $# in
1) ;;
*) die "usage: git-swapto <branch>";;
esac
require_work_tree
# From require_clean_work_tree, converted to status;
# assumes work tree exists.
work_tree_is_clean() {
git update-index -q --ignore-submodules --refresh
# if diff-files says different, fail (work tree not clean)
git diff-files --quiet --ignore-submodules || return 1
# if diff-index says index is different, fail (index not clean)
git diff-index --cached --quiet --ignore-submodules HEAD || return 1
# both work tree and index are clean => nothing to commit
return 0
}
# Force branch name as argument, since we want to do a soft
# reset if there is a temporary commit on it. Also, require
# that current HEAD name a branch.
case "$(git rev-parse --symbolic-full-name "$1")" in
refs/heads/*) ;;
*) die "`$1': not a branch name";;
esac
git symbolic-ref -q HEAD >/dev/null || die "not currently on a branch"
temp_commit_string="!! temporary commit, do not push"
# test whether HEAD refers to our temporary commit
current_commit_is_temp() {
local head_text="$(git log --no-walk --pretty=format:%B)"
test "$head_text" = "$temp_commit_string"
}
# Before leaving this branch, make a temporary commit if
# necessary, amending existing temporary commit if there is one.
# (We should never need --amend, this is just paranoia.)
if ! work_tree_is_clean; then
echo "note: leaving temp commit behind" 1>&2
if current_commit_is_temp; then
git commit -a --amend --no-edit ||
die "cannot update current temp commit"
else
git commit -a -m "$temp_commit_string" --no-edit ||
die "cannot make temp commit"
fi
fi
# work tree is now clean, switch to target
git checkout "$1" || die "cannot switch to $1"
# finally, if it is our special temp commit, reset it away
if current_commit_is_temp; then
git reset --soft HEAD^ || die "failed to unmake temp commit"
fi
# all done, for good or ill...
en fait, il fait au moins deux, et parfois trois, commits temporaires. Il s'agit plus de "mécanisme" que de "politique", alors que "pas sur une branche" est une politique/conception.
Ou, comme git stash
, utilisez deux commits si vous souhaitez conserver "index" et "travail-tree" séparément. Sinon, ajoutez simplement des éléments à l'index comme d'habitude, puis faites un seul commit.
Vous pouvez également utiliser la commande stash-and-checkout
de git-whistles. Git-whistles est une gemme Ruby, donc si vous avez installé Ruby, vous pouvez installer git-whistles avec gem install git-whistles
. Ensuite, vous pouvez simplement faire git stash-and-checkout [branch]
pour réaliser ce que vous voulez faire.
Par souci de concision, j'ai défini un alias shell g
pour git et alias git co
pour stash-and-checkout
, ainsi planquer tout travail non engagée sur la branche actuelle, passer à la nouvelle branche et pop de planque de cette branche (le cas échéant) , Je peux simplement taper g co [branch]
. Pour l'exemple de configuration d'alias git, voir mon .gitconfig au github.com/vwal/my-git-extras.