Всякий раз, когда у вас есть тайник, который не будет применяться, я рекомендую превратить этот тайник в ветвь.
Для этого сначала убедитесь, что у вас нет незавершенной работы. Это означает, что теперь вы должны фиксировать все, что делаете, или хранить его - последнее немного иронично и странно, но работает нормально, если вы помните, что преобразованный вами ключ теперь перенумерован. Теперь, когда все «чисто», выберите проблемный тайник по его идентификатору - stash@{1}
или stash@{6}
или как угодно, если это необходимо, или просто по умолчанию, если это текущий или единственный тайник - и используйте этот идентификатор (или по умолчанию) в качестве аргумент команды git stash branch
:
$ git stash branch newbranch stash@{3}
Теперь вы находитесь в состоянии, в котором вы можете запустить git status
, затем, возможно, git commit
или git add
и git commit
и т. Д. - ваш stash@{3}
тайник был повторно загружен в индекс, как если вы запустили git stash apply --index
и в свое рабочее дерево, как если бы этой же командой. Как только вы сделаете коммит (ы), ваша новая ветка готова к использованию, как вам нравится.
(Фактически, Git действительно выполнил запустил команду: сначала Git запустил git checkout
соответствующего коммита. Затем Git запустил git stash apply --index
на тайнике, который восстановил сохраненный индекс и сохраненный work-tree. Затем, успешно применив, Git запустил git stash drop
на этом сохраненном тайнике.)
В этом случае после git stash branch <em>name</em> <em>stash</em>
вам, вероятно, понадобится один git add
и git commit
, который сохранит всю вашу работу, включая надоедливую не удаленную, возможно измененную, а может быть, не UserInterfaceState.xcuserstate
файл. Но теперь вы можете git checkout
ветку, над которой вы работали , применить и сбросить временный сундук, который вы сделали, если вы его сделали, и git cherry-pick -n
коммит на ту новую ветку, которую вы сделали с вашего проблемного сундука. Если этот коммит не содержит изменений в файле pesky, а файл pesky здесь не существует, выбор вишни, скорее всего, пройдет довольно гладко, и все будет готово.
Обсуждение
Все это имеет определенный смысл, когда вы понимаете, что (a) объект git stash
- это просто коммит коммитов; (b) коммиты всегда записывают свои родительские коммиты; и (c) ветвь - это просто серия коммитов, обозначаемых веткой name , идентифицирующей last коммит, который следует считать частью ветки.
Если бы способ, которым git stash
сделал свой маленький коммит коммитов, был нормальным, вы бы получили:
...--o--o--*--o <-- your-branch
\
i--w <-- stash
и, следовательно, тайник действительно будет похож на любую ветку, за исключением того факта, что refs/stash
не начинается с refs/heads/
(сравните с refs/heads/your-branch
, который, очевидно, начинается с refs/heads/
). Здесь *
- это коммит, на котором вы были , когда запускали git stash
. Вы добавили еще один коммит, который находится справа от *
. Коммиты i
и w
будут содержать индекс и состояния рабочего дерева на момент запуска git stash
.
Сложность в том, что git stash
вообще не делает i
и w
такими. Вместо этого он делает:
...--o--o--*--o <-- your-branch
|\
i-w <-- stash
То есть сохраненное состояние рабочего дерева выглядит как коммит слияния , сохраняя результат слияния вашего индексного коммита i
и коммита, который вы использовали при запуске git stash
(коммит *
). На самом деле это не слияние, потому что это не то, что вы получите, запустив git merge
: код stash просто использует формат слияния-фиксации, чтобы сделать его проще для последующего кода.
К счастью, git stash branch
знает, как злоупотреблять форматом. Это:
- проверка фиксации
*
;
- создает новое имя ветки, чтобы помнить, где вы сейчас находитесь; и
- применяет тайник, сохраняя его компоненты индекса и рабочего дерева отдельно (как они были при сохранении тайника) на случай, если это именно то, что вы намеревались.
Итак, теперь у вас есть:
o <-- your-branch
/
...--o--o--* <-- new-branch
с i
в вашем индексе (готово для фиксации) и w
в вашем рабочем дереве (готово к git add
-ed) для обновления вашего индекса, после чего w
будет в вашем индексе и готов быть преданным). В Commit *
, конечно, есть файл pesky, поэтому оставьте файл pesky там, где он есть, без изменений, добавьте и зафиксируйте все остальное, и вы получите:
o <-- your-branch
/
...--o--o--*--W <-- new-branch
белыйere W
- это обычная обычная фиксация состояния рабочего дерева, которое вы имели, готовый быть переданным в git cherry-pick
(возможно, с -n
) или использоваться как вам угодно.
В конце концов, вы можете просто удалить ветку new-branch
(которую вы, вероятно, хотите назвать другим именем), и фиксация W
будет отменена и в конечном итоге полностью исчезнет.