it-swarm.com.ru

Как назвать и получить тайник по имени в git?

У меня всегда было впечатление, что вы можете присвоить тайнику имя, выполнив git stash save stashname, который позже вы сможете применить, выполнив git stash apply stashname. Но, похоже, что в этом случае все, что происходит, это то, что stashname будет использоваться в качестве описания тайника.

Нет ли способа на самом деле назвать тайник? Если нет, что бы вы порекомендовали для достижения эквивалентной функциональности? По сути, у меня есть небольшой тайник, который я хотел бы периодически применять, но не хочу всегда искать в git stash list, каков его фактический номер тайника.

1049
Suan

Вот как вы это делаете:

git stash save "my_stash"

где "my_stash" - это имя тайника ...

Еще несколько полезных вещей: все тайники хранятся в стеке Введите:

git stash list

Это перечислит все ваши тайники.

Чтобы применить тайник и удалить его из стопки, Вы можете дать,

git stash pop [email protected]{n}

Чтобы применить тайник и сохранить его в стеке, введите:

git stash apply [email protected]{n}

Где n в индексе припрятанного изменения.

430
Sri Murthy Upadhyayula

git stash save - это deprecated с 2.15.x/2.16, вместо этого вы можете использовать git stash Push -m "message" 

Вы можете прокудить так:

git stash Push -m "message" 

где «message» - ваше имя.

89
EssaidiM

Вы можете превратить тайник в ветку, если считаете, что это достаточно важно:

git stash branch <branchname> [<stash>]

со страницы руководства:

Это создает и проверяет новую ветвь с именем <branchname>, начиная с коммита, в котором изначально был создан <stash>, применяет изменения, записанные в <stash>, к новому рабочему дереву и индексу, а затем удаляет <stash>, если это завершается успешно. Когда <stash> не указан, применяется последний.

Это полезно, если ветвь, в которой вы запустили git stash save, изменилась настолько, что git stash не удалось применить из-за конфликтов. Поскольку хранилище применяется поверх коммита, который был HEAD во время запуска git stash, он восстанавливает исходное хранилище без конфликтов.

Позже вы можете переместить эту новую ветку в другое место, которое является потомком того места, где вы были, когда вы прятали.

76
Adam Dymitruk

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

35
Lily Ballard

Если вы просто ищете легкий способ сохранить некоторые или все текущие изменения рабочей копии, а затем повторно применить их по желанию, рассмотрите файл исправления:

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

# re-apply it later
git apply some.patch

Время от времени я задаюсь вопросом, должен ли я использовать тайники для этого, и тогда я вижу такие вещи, как безумие выше, и я доволен тем, что я делаю :) 

29
Pat Niemeyer

У меня есть две эти функции в моем файле .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
12
iWheelBuy

Кличка

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"
7
Vlastimil Ovčáčík

К сожалению, git stash apply stash^{/<regex>} не работает (на самом деле он не ищет в тайнике, см. Комментарии под принятым ответом ).

Вот вставные замены, которые ищут git stash list по регулярному выражению, чтобы найти первый (самый последний) [email protected]{<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
Zack Morris

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

Вы также можете добавить псевдоним git, чтобы найти ссылку на stash и использовать ее в других псевдонимах для show, apply, drop и т.д.

[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 нацелятся на последний тайник вместо сбоя, как и следовало ожидать.

5
Nathanael

Alias ​​ Это может быть более прямой синтаксис для Unix-подобных систем без необходимости инкапсулировать в функцию . Добавьте следующее в ~/.gitconfig в [alias]

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

Использование: sapply regex

Пример: git sshow MySecretStash

Дефис в конце говорит, что берут данные из стандартного ввода.

3
Rohanthewiz

Используйте маленький скрипт 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
Will Sheppard

Для всего, кроме создания тайника, я бы предложил другое решение, представив fzf как зависимость. Рекомендую потратить 5 минут вашего времени и познакомиться с ним, так как это в целом повышает производительность.

В любом случае, соответствующая выдержка из их страницы примеров предлагает поиск тайника. Очень легко изменить sciptlet, чтобы добавить дополнительную функциональность (например, приложение-хранилище или удаление):

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
laur

Это один из способов сделать это с помощью 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 "[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''
    }
}

Подробнее здесь

1
Geoffrey Hudik

Используйте 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 выше;)

Примечание: как говорит Кевин, вместо этого вы должны использовать теги и вишневые кирки.

1
Dan Rosenstark

Как насчет этого?

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

в моей рыбной раковине

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

использование

gsap name_of_stash

0
Matsumoto Kazuya

Здесь поздно вечером, но если вы используете VSCode, быстрый способ сделать это - открыть палитру команд (CTRL/CMD + SHIFT + P) и набрать «Pop Stash», вы сможете получить свой тайник по имени без необходимости использовать git CLI

0
Alexandre Gomes

git stash apply также работает с другими ссылками, кроме [email protected]{0}. Таким образом, вы можете использовать обычные теги , чтобы получить постоянное имя. Это также имеет то преимущество, что вы не можете случайно 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
A.H.