Git stash зависит от ветки или для всего репозитория?

95

Я зашел в ветку и поработал. Я хотел перейти в другую ветку, но не хотел делать коммит, поэтому и сделал git stash. Тогда я сделал git checkout <otherbranch>. Я поработал там, и, как и в первой ветке, я хотел выйти из нее перед тем, как приступить к работе. Я тоже git stashтам сделал . Я вернулся к первой ветке и попытался распаковать ее ( git stash pop), думая, что она получит тайник из этой конкретной ветки. Я был удивлен, что он распаковал тайник из <otherbranch>(последнего спрятанного). У меня создалось впечатление, что тайник зависит от ветки, но такое поведение указывает на то, что для всего локального репозитория существует только один тайник.

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

амфибия
источник

Ответы:

43

Чтобы увидеть текущий стек тайника:

git stash list

Чтобы выбрать конкретный тайник из стека, обратитесь к нему, как показано выше.stash@{number}

Если вы хотите, чтобы поведение было для каждой ветки, вы можете просто сделать фиксацию (или несколько коммитов) в ветке. Вы всегда можете «отменить» фиксацию (и) позже (например, с помощью git reset, либо --softили --mixed; см. Документацию по сбросу git ; или с помощью, git rebase -iчтобы сохранить только возможные «настоящие» фиксации, отбрасывая временные).

(Для реальной эмуляции git stashвам нужно как минимум две фиксации, одна для состояния индекса и одна для состояния рабочего дерева. Однако, если вы не планируете сохранять и восстанавливать состояние индекса, вы можете просто git add -Aвсе состояние рабочего дерева и поместите это во временную фиксацию. В качестве альтернативы, git stashэто сценарий оболочки, поэтому вы можете довольно легко скопировать и изменить его, чтобы он работал по каждой ветке по умолчанию, используя, например, в качестве своего рабочего пространства имен, а не один глобальный для репо целиком. Вы все равно сможете переносить тайник из одной ветки в другую, явно называя ее.)refs/pb-stash/branchrefs/stash

торек
источник
вы знаете, как отображать список файлов каждого stash listэлемента в дополнение к простому описанию?
амфибия
2
git stash show(или git stash show stash@{<number>}для чего-то другого, кроме @{0}версии) дает вам diff --stat; добавьте, -pчтобы получить большую разницу. Примечание: это сравнивает "дерево работы" в "тайнике" с фиксацией, от которой оно зависает; нет внешнего интерфейса, чтобы увидеть, что находится в "индексе" в данной сумке.
torek
55

Нет и нет. Git stash предназначен для каждого репозитория.

Вот хорошая страница о том, как его использовать.

Abasterfield
источник
второй тайник перезаписывает первый? IOW, если я сделаю два тайника, но не буду между ними, потеряю ли я первый тайник?
амфибия
1
Нет, у вас есть куча тайников (последним пришел - первым ушел). Вы вставляете тайник в свой тайник, затем другой, затем вытаскиваете вторую, затем вытаскиваете первую и т. Д.
abasterfield
18

git stash не по ветке.

  • Вместо git stash(который можно легко потерять, когда у вас много тайников и веток)
  • Я предлагаю сделать a, git commitчтобы сохранить незаконченный код в своей ветке, и когда вы будете готовы закончить код, сделайте a, git reset ${COMMIT_HASH_VALUE}чтобы вернуть незаконченный код
  • git commitи git resetпри правильном использовании вместе может имитировать a git stashдля конкретной ветви

Вот обычный сценарий в реальной жизни , который демонстрирует значение и использование в commitи resetкомандах:

  • вы работаете над функциональной веткой X, и ваш код даже не компилируется и не проходит тесты
  • есть ошибка, имеющая более высокий приоритет, чем текущая новая функция, поэтому вы должны немедленно начать работу над исправлением ошибки
  • вместо того, чтобы делать git stash (и тайник теряется в миксе, потому что у вас много тайников и много веток)
  • вы можете сделать git commitветку функции X
    • запишите COMMIT_HASH_VALUEна потом
  • проверить новую ветку Y для исправления
  • завершить оперативное исправление в ветке Y (выполнить запрос на слияние, чтобы получить оперативное исправление в базовой линии и удалить ветку оперативного исправления)
  • затем снова проверьте ветку функции X
  • чтобы вытащить незаконченную работу, которая не была скомпилирована и не прошла тестирование -> просто выполните git reset ${COMMIT_HASH_VALUE}

(FYI по умолчанию для git resetIS --mixed)

Тревор Бойд Смит
источник
2
Удобный ярлык для сброса в этом сценарии - git reset HEAD~1.
Сэм А. Хорват-Хант,
1
@samHH у меня было слишком много случаев, когда git reset HEAD ^ 1 случайно ударился дважды ... поэтому я решил не использовать HEAD^1или HEAD~1.
Тревор Бойд Смит
11

Я не уверен, почему каждый ответ здесь предлагает имитировать тайник с помощью commit+ reset. Stash отлично подходит для использования, особенно при работе с несколькими ветвями. Я также не хочу фиксировать, когда работаю с несколькими ветвями, потому что хочу, чтобы все измененные изменения по-прежнему выделялись в моем редакторе, когда я вернусь.

Итак, вот рабочий процесс тайника:

Всякий раз, когда вам нужно переключить ветку и вы не готовы к фиксации, сохраните свои изменения в стеке.

git stash save "Your custom stash message"

Когда вы вернетесь в филиал, проверьте тайник

git stash list

введите описание изображения здесь

Если вы находитесь в ветке, FixIssue0203вы можете использовать use, git stash popпотому что это применит верх stash@{0}и удалит его из тайника.

Однако, если вы ImproveReadmeнаходитесь в ветке, вы должны сначала применить тайник 1, git stash apply stash@{1}а затем удалить тайник 1 из стека git stash drop stash@{1}.

Это оно!

Адам
источник