Ich hatte immer den Eindruck, dass Sie mit git stash save stashname
einen Namen angeben können, den Sie später mit git stash apply stashname
anwenden können. In diesem Fall scheint es jedoch so, dass stashname
als Stash-Beschreibung verwendet wird.
Gibt es keine Möglichkeit, einen Vorrat zu benennen? Wenn nicht, was würden Sie empfehlen, um eine gleichwertige Funktionalität zu erreichen? Im Wesentlichen habe ich einen kleinen Vorrat, den ich regelmäßig beantragen möchte, aber ich möchte nicht immer in git stash list
nach der tatsächlichen Anzahl von Stashs suchen.
Das ist wie man es macht:
git stash save "my_stash"
wo "my_stash" der Stash-Name ist ...
Weitere nützliche Dinge zu wissen: Alle Verstecke werden in einem Stapel gespeichert.
git stash list
Dies listet alle Ihre Vorräte auf.
Um einen Vorrat anzulegen und aus dem Stapel zu entfernen, können Sie
git stash pop [email protected]{n}
Geben Sie Folgendes ein, um einen Vorrat anzuwenden und im Stapel zu behalten:
git stash apply [email protected]{n}
Wo n im Index der verstauten Änderung.
git stash save
ist veraltet ab 2.15.x/2.16, stattdessen können Sie git stash Push -m "message"
verwenden.
Sie können wie folgt vorgehen:
git stash Push -m "message"
wo "Nachricht" ist Ihr Stash-Name ...
Sie können einen Vorrat in einen Zweig verwandeln, wenn Sie das für wichtig genug halten:
git stash branch <branchname> [<stash>]
von der Manpage:
Dadurch wird ein neuer Zweig mit dem Namen <branchname> erstellt und ausgecheckt, beginnend mit dem Commit, bei dem der <stash> ursprünglich erstellt wurde. Die Änderungen, die in <stash> aufgezeichnet wurden, werden auf den neuen Arbeitsbaum und den Index angewendet und dann der <stash> gelöscht wird erfolgreich abgeschlossen. Wenn kein <Stash> angegeben ist, gilt der letzte.
Dies ist nützlich, wenn der Zweig, auf dem Sie git stash save ausgeführt haben, sich so verändert hat, dass git stash apply aufgrund von Konflikten fehlschlägt. Da der Stash zusätzlich zu dem Commit angewendet wird, das HEAD war, als git Stash ausgeführt wurde, wird der ursprünglich gespeicherte Status ohne Konflikte wiederhergestellt.
Sie können diesen neuen Zweig später an einen anderen Ort zurücklegen, der von dem Ort abhängt, an dem Sie sich befunden haben, als Sie sich verstecken.
Verstecke sind nicht als dauerhafte Dinge gedacht, die du willst. Sie werden wahrscheinlich besser mit Tags für Commits bedient. Konstruieren Sie das, was Sie unterbringen möchten. Machen Sie ein Commit daraus. Erstellen Sie ein Tag für dieses Commit. Dann rollen Sie Ihren Zweig auf HEAD^
zurück. Wenn Sie diesen Vorrat erneut anwenden möchten, können Sie git cherry-pick -n tagname
verwenden (-n
ist --no-commit
).
Wenn Sie nur nach einer einfachen Methode suchen, um einige oder alle aktuellen Änderungen der Arbeitskopie zu speichern und sie später nach Belieben erneut anzuwenden, ziehen Sie eine Patch-Datei in Betracht:
# save your working copy changes
git diff > some.patch
# re-apply it later
git apply some.patch
Ab und zu frage ich mich, ob ich dafür Stashes verwenden sollte und dann sehe ich Dinge wie den Wahnsinn oben und bin damit zufrieden, was ich tue :)
Ich habe diese beiden Funktionen in meiner .zshrc
-Datei:
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)
}
Sie auf diese Weise verwenden:
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: Ich habe an meiner ursprünglichen Lösung festgehalten, aber ich sehe, warum die Mehrheit Etan Reisners Version (oben) vorziehen würde. Also nur für die Aufzeichnung:
sapply = "!f() { git stash apply \"$(git stash list | grep -E \"$*\" | awk \"{ print $ 1; }\" | sed -n \"s/://;1p\")\"; }; f"
Es ist bedauerlich, dass git stash apply stash^{/<regex>}
nicht funktioniert (es durchsucht die Stash-Liste nicht wirklich, siehe die Kommentare unter akzeptierte Antwort ).
Hier sind Drop-In-Ersetzungen, die git stash list
mit regex durchsuchen, um den ersten (neuesten) [email protected]{<n>}
zu finden und diesen dann an git stash <command>
zu übergeben:
# 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")
Beachten Sie, dass korrekte Ergebniscodes zurückgegeben werden, damit Sie diese Befehle in anderen Skripts verwenden können. Dies kann nach dem Ausführen von Befehlen überprüft werden mit:
echo $?
Seien Sie vorsichtig bei variablen Erweiterungs-Exploits , weil ich nicht sicher war, was den --grep=$1
-Teil betrifft. Es sollte vielleicht --grep="$1"
sein, aber ich bin nicht sicher, ob dies mit Regex-Trennzeichen interferieren würde (ich bin offen für Vorschläge).
Diese Antwort verdankt Klemen Slavič viel. Ich hätte nur die akzeptierte Antwort kommentiert, aber ich habe noch nicht genug Vertreter :(
Sie können auch einen Git-Alias hinzufügen, um den stash ref zu finden und ihn in anderen Aliasnamen für das Anzeigen, Anwenden, Ablegen usw. verwenden.
[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"
Beachten Sie, dass der Grund für das ref=$( ... ); echo ${ref:-<no_match>};
-Muster darin liegt, dass keine leere Zeichenfolge zurückgegeben wird. Dies würde dazu führen, dass sshow, sapply und sdrop den neuesten Stash anvisieren, anstatt wie erwartet zu fehlschlagen.
Alias Dies könnte eine direktere Syntax für Unix-ähnliche Systeme sein, ohne dass eine Funktion in einer Funktion eingekapselt werden muss . Fügen Sie ~/.gitconfig unter [Alias] Folgendes hinzu:
sshow = !sh -c 'git stash show stash^{/$*} -p' -
sapply = !sh -c 'git stash apply stash^{/$*}' -
ssave = !sh -c 'git stash save "${1}"' -
Verwendungszweck: sapply regex
Beispiel: git sshow MySecretStash
Der Bindestrich am Ende sagt, dass die Eingabe von der Standardeingabe übernommen wird.
Verwenden Sie ein kleines Bash-Skript, um die Nummer des Vorrats zu ermitteln. Nennen Sie es "gitapply":
NAME="$1"
if [[ -z "$NAME" ]]; then echo "usage: gitapply [name]"; exit; fi
git stash apply $(git stash list | grep "$NAME" | cut -d: -f1)
Verwendungszweck:
gitapply foo
... wobei foo eine Unterzeichenfolge des Namens des gewünschten Speichers ist.
Für alles außer der Stash-Erstellung würde ich eine andere Lösung vorschlagen, indem ich fzf als Abhängigkeit einführe. Es empfiehlt sich, sich 5 Minuten Ihrer Zeit zu nehmen und sich mit ihr vertraut zu machen, da dies die Produktivität insgesamt enorm steigert.
Wie auch immer, ein verwandter Auszug aus der Beispielseite bietet Stash-Suche. Es ist sehr einfach, das Sciptlet zu ändern, um zusätzliche Funktionen hinzuzufügen (z. B. Stash-Anwendung oder Ablegen):
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
}
Dies ist eine Möglichkeit, dies mit PowerShell zu erreichen:
<#
.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 "[email protected]{0}"
#>
function Restore-Stash {
[CmdletBinding()]
[Alias("Apply-Stash")]
PARAM (
[Parameter(Mandatory=$true)] $message,
[switch]$drop
)
$stashId = $null
if ($message -match "[email protected]{") {
$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''
}
}
Verwenden Sie git stash save NAME
zum Speichern.
Dann ... können Sie mit diesem Skript auswählen, welche Anwendung (oder Pop) angewendet werden soll:
#!/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
Ich mag es, die Namen der Vorräte sehen und auswählen zu können. Ich benutze auch Zshell und wusste ehrlich gesagt nicht, wie ich einige der Bash-Aliase verwenden sollte.
Hinweis: Wie Kevin sagt, stattdessen sollten Sie Tags und Kirschpicks verwenden.
Was ist damit?
git stash save stashname
git stash apply stash^{/stashname}
in meiner Fischschale
function gsap
git stash list | grep ": $argv" | tr -dc '0-9' | xargs git stash apply
end
benutzen
gsap name_of_stash
Spät an der Party hier, aber wenn Sie VSCode verwenden, können Sie die Befehlspalette (STRG/CMD + UMSCHALTTASTE + P) schnell öffnen und "Pop Stash" eingeben, um den Speicher nach Name abzurufen ohne die git CLI verwenden zu müssen
git stash apply
funktioniert auch mit anderen Refs als [email protected]{0}
. Sie können also normale Tags verwenden, um einen persistenten Namen zu erhalten. Dies hat auch den Vorteil, dass Sie git stash drop
oder git stash pop
nicht versehentlich ausführen können.
So können Sie einen Alias pstash
(auch "persistent stash") wie folgt definieren:
git config --global alias.pstash '!f(){ git stash && git tag "$1" stash && git stash drop; }; f'
Jetzt können Sie einen getaggten Stash erstellen:
git pstash x-important-stuff
und show
und apply
es wieder wie gewohnt:
git stash show x-important-stuff
git stash apply x-important-stuff