J'ai toujours eu l'impression que vous pouviez donner un nom à une cachette en faisant git stash save stashname
, que vous pourriez ensuite appliquer en faisant git stash apply stashname
. Mais il semble que dans ce cas, tout ce qui se produit est que stashname
sera utilisé comme description de la dissimulation.
N'y a-t-il pas moyen de nommer une cachette? Si non, que recommanderiez-vous pour obtenir une fonctionnalité équivalente? J'ai essentiellement une petite réserve que j'aimerais régulièrement appliquer, mais je ne veux pas toujours avoir à chercher dans git stash list
quel est son numéro de réserve.
Voici comment vous le faites:
git stash save "my_stash"
où "my_stash" est le nom de la cachette ...
Quelques choses plus utiles à savoir: Tous les stash sont stockés dans une pile . Tapez:
git stash list
Cela listera toutes vos caches.
Pour appliquer une cachette et la retirer de la pile de cachette, vous pouvez donner,
git stash pop stash@{n}
Pour appliquer une cachette et la conserver dans la pile de cachette, tapez:
git stash apply stash@{n}
Où n dans l'index du changement caché.
git stash save
est obsolète à partir de 2.15.x/2.16, vous pouvez utiliser plutôt git stash Push -m "message"
Vous pouvez procuder comme ceci:
git stash Push -m "message"
où "message" est votre nom de réserve ...
Vous pouvez transformer une réserve en une branche si vous le jugez suffisamment important:
git stash branch <branchname> [<stash>]
depuis la page de manuel:
Cela crée et extrait une nouvelle branche nommée <nombranchée> à partir de la validation à laquelle le <stash> a été créé à l'origine, applique les modifications enregistrées dans <stash> au nouvel arbre et index de travail, puis supprime le <stash> si cela se produit. se termine avec succès. Quand aucun <stash> n'est donné, applique le dernier.
Ceci est utile si la branche sur laquelle vous avez exécuté git stash save a suffisamment changé pour que l'application de git stash échoue en raison de conflits. Comme la cachette est appliquée par-dessus le commit qui était HEAD au moment où git stash a été exécutée, il restaure l'état initialement caché sans aucun conflit.
Vous pouvez ensuite rebaser cette nouvelle branche vers un autre endroit qui est un descendant de l'endroit où vous étiez lorsque vous avez caché.
Les caches ne sont pas conçues pour être permanentes, comme vous le souhaitez. Vous seriez probablement mieux servi en utilisant des balises sur les commits. Construisez la chose que vous voulez cacher. Engagez-vous dessus. Créez une étiquette pour ce commit. Ensuite, rétablissez votre branche à HEAD^
. Maintenant, lorsque vous souhaitez réappliquer cette réserve, vous pouvez utiliser git cherry-pick -n tagname
(-n
est --no-commit
).
Si vous cherchez simplement un moyen léger d’enregistrer une partie ou la totalité de vos modifications de copie de travail actuelles et de les réappliquer ultérieurement à volonté, envisagez un fichier de correctif:
# 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 cela, puis je vois des choses comme la folie ci-dessus et je suis content de ce que je fais :)
J'ai ces deux fonctions dans mon fichier .zshrc
:
function gitstash() {
git stash Push -m "zsh_stash_name_$1"
}
function gitstashapply() {
git stash apply $(git stash list | grep "zsh_stash_name_$1" | cut -d: -f1)
}
En les utilisant de cette façon:
gitstash Nice
gitstashapply Nice
sapply = "!f() { git stash apply \"$(git stash list | awk -F: --posix -vpat=\"$*\" \"$ 0 ~ pat {print $ 1; exit}\")\"; }; f"
git sapply "<regex>"
Edit: je suis resté fidèle à ma solution originale, mais je vois pourquoi la majorité préférerait la version d'Etan Reisner (ci-dessus). Donc, juste pour l'enregistrement:
sapply = "!f() { git stash apply \"$(git stash list | grep -E \"$*\" | awk \"{ print $ 1; }\" | sed -n \"s/://;1p\")\"; }; f"
Il est regrettable que git stash apply stash^{/<regex>}
ne fonctionne pas (il ne fait pas de recherche dans la liste de dissimulation, voir les commentaires sous réponse acceptée ).
Voici les remplacements instantanés qui recherchent git stash list
par regex pour trouver le premier (le plus récent) stash@{<n>}
, puis le transmettent à 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=$1 | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash show "$n" ; else echo "Error: No stash matches $1" ; return 1 ; fi }; f"
sapply = "!f() { n=$(git stash list --max-count=1 --grep=$1 | cut -f1 -d":") ; if [[ -n "$n" ]] ; then git stash apply "$n" ; else echo "Error: No stash matches $1" ; 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 renvoyés afin que vous puissiez utiliser ces commandes dans d'autres scripts. Ceci peut être vérifié après avoir exécuté des commandes avec:
echo $?
Faites juste attention aux exploits de développement de variable parce que je n’étais pas sûr de la partie --grep=$1
. Cela devrait peut-être être --grep="$1"
mais je ne suis pas sûr que cela interfère avec les délimiteurs de regex (je suis ouvert aux suggestions).
Cette réponse doit beaucoup à Klemen Slavič. J'aurais juste commenté la réponse acceptée mais je n'ai pas encore assez de représentants :(
Vous pouvez également ajouter un alias git pour trouver la référence de masquage et l’utiliser dans d’autres alias pour afficher, appliquer, déposer, etc.
[alias]
sgrep = "!f() { ref=$(git --no-pager stash list | grep "$1" | cut -d: -f1 | head -n1); echo ${ref:-<no_match>}; }; f"
sshow = "!f() { git stash show $(git sgrep "$1") -p; }; f"
sapply = "!f() { git stash apply $(git sgrep "$1"); }; f"
sdrop = "!f() { git stash drop $(git sgrep "$1"); }; f"
Notez que la raison du modèle ref=$( ... ); echo ${ref:-<no_match>};
est qu’une chaîne vide n’est pas renvoyée, ce qui obligerait sshow, sapply et sdrop à cibler le dernier stash au lieu d’échouer comme prévu.
Alias Cela pourrait être une syntaxe plus directe pour les systèmes de type Unix sans avoir besoin d'encapsuler dans une fonction . Ajouter 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 "${1}"' -
Usage: sapply regex
Exemple: git sshow MySecretStash
Le trait d'union à la fin indique de prendre une entrée de l'entrée standard.
Utilisez un petit script bash pour rechercher le numéro de la réserve. Appelez ça "gitapply":
NAME="$1"
if [[ -z "$NAME" ]]; then echo "usage: gitapply [name]"; exit; fi
git stash apply $(git stash list | grep "$NAME" | cut -d: -f1)
Usage:
gitapply foo
... où foo est une sous-chaîne du nom de la réserve que vous voulez.
Pour toute chose en plus de la création de stash, je proposerais une autre solution en introduisant fzf en tant que dépendance. Nous vous recommandons de prendre 5 minutes de votre temps et de vous y familiariser, car c’est un excellent stimulant de la productivité.
Quoi qu'il en soit, un extrait connexe de leur page exemples offrant une recherche cachée. Il est très facile de changer le sciptlet pour ajouter des fonctionnalités supplémentaires (telles que l'application stash ou drop):
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 un moyen de réaliser cela à l’aide de 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''
}
}
Utilisez git stash save NAME
pour enregistrer.
Ensuite ... vous pouvez utiliser ce script pour choisir lequel appliquer (ou apparaître):
#!/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. Aussi, j'utilise Zshell et franchement, je ne savais pas comment utiliser certains des alias Bash ci-dessus;
Remarque: comme le dit Kevin, vous devriez plutôt utiliser des balises et des sélections.
Et ça?
git stash save stashname
git stash apply stash^{/stashname}
dans ma coquille de poisson
function gsap
git stash list | grep ": $argv" | tr -dc '0-9' | xargs git stash apply
end
utilisation
gsap name_of_stash
En retard pour la partie, mais si vous utilisez VSCode, un moyen rapide de le faire est d'ouvrir la palette de commandes (CTRL/CMD + SHIFT + P) et de taper "Pop Stash", vous pourrez récupérer votre stash par nom sans avoir besoin d'utiliser git CLI
git stash apply
fonctionne également avec d'autres références que stash@{0}
. Vous pouvez donc utiliser tags pour obtenir un nom persistant. Cela a aussi l’avantage que vous ne pouvez pas accidentellement git stash drop
ou git stash pop
le.
Donc, vous pouvez définir un alias pstash
(aka "stash persistant") comme ceci:
git config --global alias.pstash '!f(){ git stash && git tag "$1" stash && git stash drop; }; f'
Maintenant, vous pouvez créer une réserve marquée:
git pstash x-important-stuff
et show
et apply
comme d'habitude:
git stash show x-important-stuff
git stash apply x-important-stuff