Comment nommer et récupérer une cachette par nom dans git?
j'ai toujours eu l'impression que l'on pouvait donner un nom à une cachette en faisant git stash save stashname
, que l'on pouvait ensuite appliquer en faisant git stash apply stashname
. Mais il semble que dans ce cas tout ce qui se passe, c'est que stashname
sera utilisée comme cachette description.
N'y a-t-il aucun moyen de nommer une cachette? Dans la négative, que recommanderiez-vous pour obtenir une fonctionnalité équivalente? Essentiellement, j'ai une petite réserve que je voudrais périodiquement appliquer, mais ne pas voulez toujours avoir à chasser dans git stash list
ce que son numéro de stash réel est.
15 réponses
vous pouvez effectivement trouver la cachette par son nom en utilisant la syntaxe d'expression régulière de git pour adresser les objets:
stash^{/<regex>}
:/<regex>
par exemple, lorsque vous sauvegardez votre stock avec un nom d'enregistrement:
git stash save "guacamole sauce WIP"
... vous pouvez utiliser une expression régulière pour adresser cette cachette:
git stash apply stash^{/guacamo}
cela s'applique à la plus jeune cachette qui correspond à l'expression régulière guacamo
. De cette façon, vous ne devez pas savoir quel nombre le stash est dans la pile, vous avez juste à savoir son nom. Il n'y a pas de syntaxe terser pour cela, mais vous pouvez créer un alias dans votre fichier .gitconfig
:
[alias]
sshow = "!f() { git stash show stash^{/$*} -p; }; f"
sapply = "!f() { git stash apply stash^{/$*}; }; f"
vous pouvez alors utiliser git sapply <regex>
pour appliquer cette cachette (sans laisser tomber).
vous pouvez alors utiliser git sshow <regex>
pour afficher: fichiers modifiés, insertions et suppressions
EDIT: Accessoires ce StackOverflow réponse sur la façon d'utiliser les arguments bash dans les alias git.
EDIT 2: cette réponse contenait les alias drop
et list
, mais je les ai supprimés depuis, puisque drop
nécessite la syntaxe stash@{n}
alors que list
ne filtre pas du tout les cachettes. Si quelqu'un sait comment résoudre un hash SHA-1 stash à un ref stash, alors je pourrais mettre en œuvre les autres commandes aussi.
EDIT 3: Par isyi la suggestion, j'ai ajouté un patch drapeau pour montrer ce que le contenu de la cachette sont lors de la démonstration.
C'est comment vous le faites:
git stash save "my_stash"
où "my_stash" est le nom de la planque...
quelques choses plus utiles à savoir: toutes les caches sont stockées dans une pile. Tapez:
git stash list
cette liste énumérera toutes vos cachettes.
pour appliquer une cachette et la retirer de la pile, vous pouvez donner,
git stash pop stash@{n}
pour mettre une cachette et la garder dans la pile, tapez:
git stash apply stash@{n}
Où n dans l'indice de la variation cachée.
vous pouvez transformer une réserve en branche si vous pensez qu'elle est assez importante:
git stash branch <branchname> [<stash>]
de la page de manuel:
cela crée et vérifie une nouvelle branche nommée
c'est utile si la branche sur laquelle vous avez lancé git stash save a suffisamment changé que git stash apply échoue en raison de conflits. Puisque la cachette est appliquée sur le dessus de la commit qui était HEAD au moment où la cachette git a été exécutée, il restaure l'état initialement caché sans conflits.
vous pouvez plus tard rebaser cette nouvelle branche à un autre endroit qui est un descendant de l'endroit où vous étiez quand vous avez caché.
les cachettes ne sont pas faites pour être des choses permanentes comme vous voulez. Vous seriez probablement mieux servi en utilisant des étiquettes sur les commet. Construire la chose que vous voulez cachette. Faire un commit. Créer une balise pour ce commit. Puis, ramenez votre branche à HEAD^
. Maintenant, quand vous voulez reappliquer cette cachette, vous pouvez utiliser git cherry-pick -n tagname
( -n
est --no-commit
).
git stash save
est obsolète maintenant, au lieu de cela, vous pouvez utiliser le bouton git stash push -m "message"
vous pouvez procude comme ceci:
git stash push -m "message"
où "message" est votre nom de planque...
si vous êtes à la recherche d'un moyen léger de sauvegarder une partie ou la totalité de vos modifications actuelles de la copie de travail et de les appliquer à nouveau plus tard à volonté, considérez un fichier patch:
# save your working copy changes
git diff > some.patch
# re-apply it later
git apply some.patch
de temps en temps je me demande si je devrais utiliser des cachettes pour ceci et puis je vois des choses comme la folie ci-dessus et je suis satisfait de ce que je fais:)
Alias
sapply = "!f() { git stash apply \"$(git stash list | awk -F: --posix -vpat=\"$*\" \"$ 0 ~ pat {print $ 1; exit}\")\"; }; f"
Utilisation
git sapply "<regex>"
- compatible avec Git for Windows
Edit: j'ai collé à ma solution originale, mais je vois pourquoi la majorité préfère Etan Reisner version (ci-dessus). Donc, juste pour le dossier:
sapply = "!f() { git stash apply \"$(git stash list | grep -E \"$*\" | awk \"{ print $ 1; }\" | sed -n \"s/://;1p\")\"; }; f"
cette réponse doit beaucoup à Klemen Slavič. J'aurais simplement commenté la réponse acceptée, mais je n'ai pas encore assez de rép.: (
vous pouvez également ajouter un alias git pour trouver l'ref stash et l'utiliser dans d'autres Alias pour show, apply, drop, etc.
[alias]
sgrep = "!f() { ref=$(git --no-pager stash list | grep "" | cut -d: -f1 | head -n1); echo ${ref:-<no_match>}; }; f"
sshow = "!f() { git stash show $(git sgrep "") -p; }; f"
sapply = "!f() { git stash apply $(git sgrep ""); }; f"
sdrop = "!f() { git stash drop $(git sgrep ""); }; f"
notez que la raison pour le motif ref=$( ... ); echo ${ref:-<no_match>};
est donc une chaîne vierge n'est pas retourné qui ferait sshow, sapply et sdrop de cibler la dernière cachette au lieu de fail comme un attendez.
Alias Cela pourrait être une syntaxe plus directe pour les systèmes de type Unix sans avoir besoin d'encapsuler dans une fonction. Ajoutez ce qui suit à ~/.gitconfig sous [alias]
sshow = !sh -c 'git stash show stash^{/$*} -p' -
sapply = !sh -c 'git stash apply stash^{/$*}' -
ssave = !sh -c 'git stash save ""' -
Usage: sapply regex
exemple: gitshow MySecretStash
Le trait d'union à la fin, dit de prendre l'entrée standard.
j'ai ces deux fonctions dans mon fichier .zshrc
:
function gitstash() {
git stash push -m "zsh_stash_name_"
}
function gitstashapply() {
git stash apply $(git stash list | grep "zsh_stash_name_" | cut -d: -f1)
}
en les utilisant de cette façon:
gitstash nice
gitstashapply nice
pour tout en dehors de la création de stash, je proposerais une autre solution en introduisant fzf comme dépendance. Recommandez de prendre 5 minutes de votre temps et de se présenter à elle, car il est sur-tous grande productivité booster.
de toute façon, un extrait connexe de leur page exemples offrant la recherche de cachette. Il est très facile de changer le sciptlet pour ajouter des fonctionnalités supplémentaires (comme stash application ou droping):
fstash() {
local out q k sha
while out=$(
git stash list --pretty="%C(yellow)%h %>(14)%Cgreen%cr %C(blue)%gs" |
fzf --ansi --no-sort --query="$q" --print-query \
--expect=ctrl-d,ctrl-b); do
mapfile -t out <<< "$out"
q="${out[0]}"
k="${out[1]}"
sha="${out[-1]}"
sha="${sha%% *}"
[[ -z "$sha" ]] && continue
if [[ "$k" == 'ctrl-d' ]]; then
git diff $sha
elif [[ "$k" == 'ctrl-b' ]]; then
git stash branch "stash-$sha" $sha
break;
else
git stash show -p $sha
fi
done
}
C'est une façon d'accomplir ceci en utilisant PowerShell:
<#
.SYNOPSIS
Restores (applies) a previously saved stash based on full or partial stash name.
.DESCRIPTION
Restores (applies) a previously saved stash based on full or partial stash name and then optionally drops the stash. Can be used regardless of whether "git stash save" was done or just "git stash". If no stash matches a message is given. If multiple stashes match a message is given along with matching stash info.
.PARAMETER message
A full or partial stash message name (see right side output of "git stash list"). Can also be "@stash{N}" where N is 0 based stash index.
.PARAMETER drop
If -drop is specified, the matching stash is dropped after being applied.
.EXAMPLE
Restore-Stash "Readme change"
Apply-Stash MyStashName
Apply-Stash MyStashName -drop
Apply-Stash "stash@{0}"
#>
function Restore-Stash {
[CmdletBinding()]
[Alias("Apply-Stash")]
PARAM (
[Parameter(Mandatory=$true)] $message,
[switch]$drop
)
$stashId = $null
if ($message -match "stash@{") {
$stashId = $message
}
if (!$stashId) {
$matches = git stash list | Where-Object { $_ -match $message }
if (!$matches) {
Write-Warning "No stashes found with message matching '$message' - check git stash list"
return
}
if ($matches.Count -gt 1) {
Write-Warning "Found $($matches.Count) matches for '$message'. Refine message or pass 'stash{@N}' to this function or git stash apply"
return $matches
}
$parts = $matches -split ':'
$stashId = $parts[0]
}
git stash apply ''$stashId''
if ($drop) {
git stash drop ''$stashId''
}
}
Utiliser git stash save NAME
pour enregistrer.
alors... vous pouvez utiliser ce script pour choisir d'appliquer (ou pop):
#!/usr/bin/env ruby
#git-stash-pick by Dan Rosenstark
# can take a command, default is apply
command = ARGV[0]
command = "apply" if !command
ARGV.clear
stashes = []
stashNames = []
`git stash list`.split("\n").each_with_index { |line, index|
lineSplit = line.split(": ");
puts "#{index+1}. #{lineSplit[2]}"
stashes[index] = lineSplit[0]
stashNames[index] = lineSplit[2]
}
print "Choose Stash or ENTER to exit: "
input = gets.chomp
if input.to_i.to_s == input
realIndex = input.to_i - 1
puts "\n\nDoing #{command} to #{stashNames[realIndex]}\n\n"
puts `git stash #{command} #{stashes[realIndex]}`
end
j'aime pouvoir voir les noms des cachettes et choisir. J'utilise aussi Zshell et franchement je ne savais pas comment utiliser certains des alias de Bash ci-dessus;)
Note: Comme Kevin dit, vous devriez utiliser des étiquettes et des pics à la place.
utilisez un petit script bash pour chercher le numéro de la cachette. Appelez-le "gitapply":
NAME=""
if [[ -z "$NAME" ]]; then echo "usage: gitapply [name]"; exit; fi
git stash apply $(git stash list | grep "$NAME" | cut -d: -f1)
Utilisation:
gitapply foo
...où foo est une soustraction du nom de la cachette que vous voulez.
il est regrettable que git stash apply stash^{/<regex>}
ne fonctionne pas (il ne fait pas réellement la recherche de la liste de stash, voir les commentaires sous le réponse acceptée ).
Voici des remplaçants qui cherchent git stash list
par regex pour trouver le premier (Le plus récent) stash@{<n>}
et passer ensuite à git stash <command>
:
# standalone (replace <stash_name> with your regex)
(n=$(git stash list --max-count=1 --grep=<stash_name> | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash show "$n" ; else echo "Error: No stash matches" ; return 1 ; fi)
(n=$(git stash list --max-count=1 --grep=<stash_name> | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash apply "$n" ; else echo "Error: No stash matches" ; return 1 ; fi)
# ~/.gitconfig
[alias]
sshow = "!f() { n=$(git stash list --max-count=1 --grep= | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash show "$n" ; else echo "Error: No stash matches " ; return 1 ; fi }; f"
sapply = "!f() { n=$(git stash list --max-count=1 --grep= | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash apply "$n" ; else echo "Error: No stash matches " ; return 1 ; fi }; f"
# usage:
$ git sshow my_stash
myfile.txt | 1 +
1 file changed, 1 insertion(+)
$ git sapply my_stash
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: myfile.txt
no changes added to commit (use "git add" and/or "git commit -a")
notez que les codes de résultat appropriés sont retournés afin que vous puissiez utiliser ces commandes d'autres scripts. Ceci peut être vérifié après avoir exécuté des commandes avec:
echo $?
il suffit de faire attention à variable expansion exploits parce que je n'étais pas sûr de la partie --grep=
. Il devrait peut-être être --grep=""
mais je ne suis pas sûr que cela interférerait avec les délimiteurs regex (je suis ouvert aux suggestions).