Як назвати та отримати скриньку за іменем у git?


1418

У мене завжди було враження, що ти можеш дати ім’я, роблячи це git stash save stashname, чим згодом ти можеш подати заявку git stash apply stashname. Але здається, що в цьому випадку все, що трапляється, - це те, що stashnameбуде використано як опис скриньки.

Чи немає способу насправді назвати скриньку? Якщо ні, що б Ви порадили досягти рівноцінної функціональності? По суті, у мене є невеликий сховище, яке я періодично хотів би застосувати, але не хочу завжди шукати, у git stash listчому його фактичний номер.


68
git stash push -m stashnameє поточним синтаксисом . git stash save stashnameзастаріло.
SherylHohman

1
git stash push -m stashname не працює в 2.8.0.Windows.1.
Жак

Git для Windows 2.26.0 виходить кілька днів тому. Можливо, це тепер виправлено. github.com/git-for-windows/git/releases/tag/v2.26.0.windows.1
tom_mai78101

Відповіді:


815

Ось як ви це робите:

git stash save "my_stash"

Де "my_stash"назва схована.

Ще кілька корисних речей, які потрібно знати: Усі сховища зберігаються в стеці. Тип:

git stash list

Це перерахує всі ваші скрині.

Щоб застосувати копію та вилучити її із стеку, введіть:

git stash pop stash@{n}

Щоб застосувати копію та зберегти її в стеці, введіть:

git stash apply stash@{n}

Де nіндекс прихованої зміни.


88
Це не дає відповіді на запитання. За замовчуванням у вас з'являється купа цифр для вашої скриньки, але це не відповідає тому, як ви можете поставити ім'я для ідентифікації легко.
GoodSp33d

16
ОП явно намагається уникнути незграбно названих імен stash @ {n} для власних імен. git stash apply <custom-name>
тушковане м'ясо

10
Не відповідає на запитання щодо отримання скриньки на ім'я.
nullsteph

45
git stash push -m my_stashє поточним синтаксисом . git stash save my_stashзастаріло.
SherylHohman

21
Це не має значення. Це корисно.
Гаян Веракутті

440

git stash saveє застарілим , як з 2.15.x / 2.16, замість цього ви можете використовуватиgit stash push -m "message"

Ви можете використовувати його так:

git stash push -m "message"

де "повідомлення" - ваша примітка до цього сховища.

Для того , щоб відновити тайник , ви можете використовувати: git stash list. Це виведе такий список, наприклад:

stash@{0}: On develop: perf-spike
stash@{1}: On develop: node v10

Тоді ви просто використовуєте applyйого stash@{index}:

git stash apply stash@{1}

Посилання на сторінку git stash man


9
Документи, pushа не saveсинтаксис: git stash push
SherylHohman

30
Це справжня відповідь. На жаль, над ним є багато старих відповідей.
малан

1
Більш детальну інформацію про нову git stash push: stackoverflow.com/a/47231547/6309
VonC

джерело (на останньому поточному документі) для повідомлення про депрекацію
Габріель

1
FWIW: Працюючи git stash apply stash@{1}в Powershell, ви отримаєте error: unknown switch 'e'спину. Замість цього скористайтеся git stash apply --index 1або git stash apply 'stash@{1}'втечі, }і {натисніть `.
ЛосМанос

104

Ви можете перетворити сховище у гілку, якщо вам здається, що це досить важливо:

git stash branch <branchname> [<stash>]

зі сторінки чоловіка:

Це створює та перевіряє нову гілку, названу, <branchname>починаючи з комітету, на якому <stash>спочатку створено, застосовує зміни, записані в <stash>новому робочому дереві та індексі, а потім видаляє, <stash>якщо це успішно завершується. Якщо не <stash>вказано, застосовується остання.

Це корисно, якщо гілка, на якій ви працювали git stash save, змінилася достатньо, щоб застосувати скрипт git не вдалося через конфлікти. Оскільки приховування застосовано поверх комітету, який був HEAD під час запуску git stash, він відновлює початково сховане стан без конфліктів.

Пізніше ви можете перенести цю нову гілку в інше місце, яке є нащадком, де ви були, коли ви переховувались.


1
Оскільки гілки досить дешеві в git, ця пропозиція мені найбільше корисна.
Джаян

5
Звичайно, але це не допомагає, якщо ви хочете продовжувати повторно застосовувати цю скриньку в різних галузях, як це просить ОП. Вам би довелося вибрати його голову.
тушковане м'ясо

@AdamDymitruk Чи є якийсь спосіб виконати це, зберігаючи приховування без попингу. (як у git stash apply)
Kasun Siyambalapitiya

Дивно, коли я спробував це, я отримав повідомлення про помилку, що один із моїх файлів буде перезаписаний під час перевірки, і я повинен здійснити або приховати (!) Свої зміни. git stash push -m 'name'працювали.
wortwart

@AdamDymmitruk дивовижна відповідь. підірвав мій розум.
День

75

Якщо ви просто шукаєте легкий спосіб зберегти деякі чи всі ваші поточні зміни в робочій копії, а потім повторно застосувати їх згодом за бажанням, врахуйте файл виправлення:

# save your working copy changes
git diff > some.patch

# re-apply it later
git apply some.patch

Раз у раз мені цікаво, чи варто мені використовувати для цього приховування, а потім я бачу такі речі, як божевілля, і я задоволений тим, що роблю :)


2
Ось воно! Дякую. Я також оновив .gitignore, щоб ігнорувати .patch файли, і я готовий мати стільки патчів, скільки я хочу.
ЛІГА

Я бачу задум, що стоїть за запитанням, що полягає в тому, щоб застосовувати деякі локальні зміни щоразу, коли виймаєте гілку з головного, а не здійснюєте їх. Тож, можливо, питання слід було б виправити, і ця відповідь повинна була бути прийнята як рішення. Також просто.
анк

46

Стейші не мають бути постійними речами, як ти хочеш. Напевно, вам краще послужити теги на комітах. Побудуйте те, що хочете сховати. Зробіть з неї зобов’язання. Створіть тег для цього коміту. Потім поверніть свою філію до HEAD^. Тепер, коли ви хочете знову застосувати цю скриньку, ви можете використовувати git cherry-pick -n tagname( -nє --no-commit).


1
Безумовно, як такий підхід, відчуває себе трохи чистішим, щоб просто named commitдесь провести час. Лише легке роздратування полягає в тому, що він не буде вчинятись при виборі вишні та залишається в розрізі, а це означає, що його потрібно буде вручну не перевіряти під час наступного комітету.
Адітя МП

1
Це найближче. Я думаю, я зроблю для цього кілька псевдонімів. Мені не подобається використовувати опис як "ім'я".
тушковане м'ясо

Соромно це додає до індексу, і вам доведеться скинути, хтось повинен виправити --no-stageваріант! Пов'язаний: stackoverflow.com/questions/32333383 / ...
Чіро Сантіллі冠状病毒审查六四事件法轮功

41

використовувати git stash push -m aNameForYourStashдля збереження. Потім скористайтеся git stash listдля вивчення індексу скриньки, який ви хочете застосувати. Потім використовуйте git stash pop --index 0для висипки та застосуйте її.

Примітка. Я використовую git версії 2.21.0.Windows.1


1
Ваша відповідь номінально, якою буде відповідь з найвищим рейтингом, беручи до уваги цей коментар до поточного синтаксисуgit stash {push,save}
Майкл - Де Clay

32

У моєму .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)
}

Використовуючи їх таким чином:

gitstash nice

gitstashapply nice

Що таке "zsh_stash_name_"?
Сем Хаслер

1
@SamHasler - лише якийсь випадковий унікальний рядок. Якщо ви хочете знати, що пристрій створено за допомогою регулярного
скрипту для

Елегантне рішення для любителів псевдоніму
suarsenegger

22

Як що до цього?

git stash save stashname
git stash apply stash^{/stashname}

1
Це звучить як щось подібне, що раніше було прийнятою відповіддю, але з тих пір було видалено.
Майкл - Де Клей

Гм, тоді чому його видалили?
АдамБ

Я не знаю, оскільки я не опублікував відповіді і не маю 10 000 репутації, але я припускаю, що це має щось спільне з коментарями, які говорять, що це не працює: це прикро, що git stash apply stash^{/<regex>}не працює (це не працює насправді шукайте список сховань, дивіться коментарі під прийнятою відповіддю ).
Майкл - Де Клей

це відповідь, яку ви шукаєте!
kiedysktos

1
для отримання я заходжу 1., git stash listщо показує мені статистику разом із їхнім асоційованим номером індексу, тоді я йду 2. git stash apply 0- де 0 - це індексний номер, я би підняв очі з першої команди
ambidexterous

8

Псевдонім

sapply = "!f() { git stash apply \"$(git stash list | awk -F: --posix -vpat=\"$*\" \"$ 0 ~ pat {print $ 1; exit}\")\"; }; f"

Використання

git sapply "<regex>"

  • сумісний з Git для Windows

Редагувати: Я дотримувався свого оригінального рішення, але бачу, чому більшість вважає за краще версію Ітана Рейснера (вище). Тож для запису:

sapply = "!f() { git stash apply \"$(git stash list | grep -E \"$*\" | awk \"{ print $ 1; }\" | sed -n \"s/://;1p\")\"; }; f"

Використання awk -F: '{print $1}'позбавило б потреби в седі повністю. Також навіщо вкручувати це у функції? І використання також awk -F: -vpat="$*" '$0 ~ pat {print $1}'повинно дозволяти скинути греп. Хоча це може вимагати трохи іншого котирування для шаблону.
Ітан Рейснер

@EtanReisner: ваш фрагмент виводить більше одного рядка.
Властиміл Овчачик

Зробіть дію, {print $1; exit}щоб вийти після першого узгодженого рядка.
Ітан Рейснер

@EtanReisner: Після деяких випробувань я міг позбутися sed, але обгортка та греп залишаються.
Властиміл Овчачик

Вам не потрібен греп, хоча, як я сказав, цитування шаблонів може відрізнятися без нього. Я припускаю, що під обгорткою ви маєте на увазі функцію оболонки? Ви ніколи не пояснювали, чому ви думаєте, що вам це потрібно, тому я не можу коментувати, чи дійсно ви це робите, але я вважаю, що ви, ймовірно, цього не зробите. (Можливо, вам доведеться вручну викликати оболонку замість git stash безпосередньо, але можливо навіть не це.)
Etan Reisner

8

Прикро, що git stash apply stash^{/<regex>}це не працює (він насправді не шукає в списку скриньки, дивіться коментарі під прийнятою відповіддю ).

Ось замінні елементи, що шукають, що шукають git stash listза допомогою регулярного виразу, щоб знайти перший (найновіший), stash@{<n>}а потім передати його 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")

Зауважте, що відповідні коди результатів повертаються, щоб ви могли використовувати ці команди в інших сценаріях. Це можна перевірити, виконавши команди за допомогою:

echo $?

Будьте обережні щодо експлуатування змінних розширень, тому що я не був впевнений у --grep=$1частині. Можливо, це може бути, --grep="$1"але я не впевнений, чи це заважатиме розмежувачам регулярних виразів (я відкритий для пропозицій).


6

Ця відповідь багато в чому завдячує Клемену Славичу. Я б просто прокоментував прийняту відповідь, але у мене ще недостатньо репліку :(

Ви також можете додати псевдонім git, щоб знайти скриньку ref і використовувати його в інших псевдонімах для показу, застосування, видалення тощо.

[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"

Зауважте, що причина ref=$( ... ); echo ${ref:-<no_match>};шаблону полягає в тому, що порожня рядок не повертається, що призведе до того, щоб sshow, sapply та sdrop націлили на останню скриньку замість невдачі, як можна було очікувати.


1
Це працює для мене, поки прийнята відповідь, здається, не працює (див. Мою оцінку прийнятої відповіді)
Jan Rüegg,

4

Псевдонім Це може бути більш прямим синтаксисом для Unix-подібних систем, не потребуючи інкапсуляції у функції. Додайте наступне до ~ / .gitconfig у розділі [псевдонім]

sshow = !sh -c 'git stash show stash^{/$*} -p' -
sapply = !sh -c 'git stash apply stash^{/$*}' -
ssave = !sh -c 'git stash save "${1}"' -

Використання: sapply регулярний вираз

Приклад: git sshow MySecretStash

Дефіс в кінці говорить приймати введення зі стандартного вводу.


4

Використовуйте невеликий скрипт bash, щоб шукати номер скриньки. Назвіть це "gitapply":

NAME="$1"
if [[ -z "$NAME" ]]; then echo "usage: gitapply [name]"; exit; fi
git stash apply $(git stash list | grep "$NAME" | cut -d: -f1)

Використання:

gitapply foo

... де foo є підрядком імені скриньки, яку ви хочете.


3

Використовуйте git stash save NAMEдля збереження.

Потім ... ви можете використовувати цей скрипт, щоб вибрати, який застосувати (або поп):

#!/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

Мені подобається, що я можу бачити назви штатів і вибирати. Також я використовую Zshell і, відверто кажучи, не знаю, як використовувати деякі псевдоніми Bash вище;)

Примітка. Як каже Кевін, вам слід використовувати мітки та вишні.


git stash saveзастаріло на користь git stash push.
wranvaud

2

Це один із способів досягти цього за допомогою 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''
    }
}

Детальніше тут


2

в моїй рибній шкаралупі

function gsap
  git stash list | grep ": $argv" | tr -dc '0-9' | xargs git stash apply
end

використання

gsap name_of_stash


Так! Дякую!!!
clozach

1

Пізно до партії тут, але якщо ви використовуєте VSCode, швидкий спосіб зробити це - відкрити палітру команд (CTRL / CMD + SHIFT + P) та ввести "Pop Stash", ви зможете отримати свою скриньку за назвою без необхідності використання git CLI


1

git stash applyтакож працює з іншими реф stash@{0}. Таким чином, ви можете використовувати звичайні теги, щоб отримати стійке ім’я. Це також має ту перевагу , що ви не можете accidentaly git stash dropабо git stash popце.

Таким чином, ви можете визначити псевдонім pstash(він же "стійкий скринька") так:

git config --global alias.pstash '!f(){ git stash && git tag "$1" stash && git stash drop; }; f'

Тепер ви можете створити теги, що позначені тегами:

git pstash x-important-stuff

і showі applyце знову , як завжди:

git stash show x-important-stuff
git stash apply x-important-stuff

0

Я не думаю, що існує спосіб зібрати покров під його ім'ям.

Я створив функцію bash, яка це робить.

#!/bin/bash

function gstashpop {
  IFS="
"
  [ -z "$1" ] && { echo "provide a stash name"; return; }
  index=$(git stash list | grep -e ': '"$1"'$' | cut -f1 -d:)
  [ "" == "$index" ] && { echo "stash name $1 not found"; return; }
  git stash apply "$index"
}

Приклад використання:

[~/code/site] on master*
$ git stash push -m"here the stash name"
Saved working directory and index state On master: here the stash name

[~/code/site] on master
$ git stash list
stash@{0}: On master: here the stash name

[~/code/site] on master
$ gstashpop "here the stash name"

Я сподіваюся, що це допомагає!


0

Для всього, крім створення скриньки , я б запропонував інше рішення, запровадивши fzf як залежність. Я рекомендую зайняти 5 хвилин вашого часу і ознайомитись з ним, оскільки це все-таки велике підвищення продуктивності.

У будь-якому випадку, пов'язаний уривок зі сторінки їх прикладів, що пропонує пошук сховано. Дуже просто змінити скрипт, щоб додати додаткову функціональність (наприклад, приховування програми або випадання):

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
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.