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.

965
demandé sur Geoffrey Hale 2012-06-30 01:33:21

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.

1192
répondu Klemen Slavič 2017-05-23 11:47:32

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.

337
répondu Sri Murthy Upadhyayula 2014-09-16 18:08:23

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 à partir de la propagation à laquelle le a été créé à l'origine, applique les changements enregistrés dans à la nouvelle arborescence et à l'index de travail, puis supprime le si cela réussit. Si aucun n'est indiqué, appliquer le dernier.

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é.

67
répondu Adam Dymitruk 2012-11-05 17:37:06

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 ).

34
répondu Kevin Ballard 2012-06-29 21:39:34

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...

20
répondu EssaidiM 2018-03-29 15:08:43

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:)

15
répondu Pat Niemeyer 2017-11-10 16:06:23

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"
7
répondu Vlastimil Ovčáčík 2013-12-22 20:56:29

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.

5
répondu Nathanael 2018-01-11 01:30:02

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.

3
répondu Rohanthewiz 2014-08-22 17:55:45

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
2
répondu iWheelBuy 2018-07-09 05:59:35

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
}
1
répondu laur 2016-09-10 11:58:54

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''
    }
}

plus de détails ici

1
répondu Geoffrey Hudik 2017-07-20 19:35:00

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.

1
répondu Dan Rosenstark 2017-07-20 20:31:06

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.

1
répondu Will Sheppard 2018-02-19 12:56:59

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).

1
répondu Zack Morris 2018-09-21 14:45:53