2016-05-05 1 views
0

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

0

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.

1

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.