Раздел «TL; DR»: остерегайтесь просто слепо делать git stash save && git checkout ... && git stash pop
.
На самом деле есть несколько частей, которые вы можете разделить, особенно при использовании интерфейса командной строки git.
В частности, «текущая ветка», если таковая имеется, представляет собой просто элемент, записанный в файле (файл, содержащий ссылку HEAD
, .git/HEAD
). Рассматривая исходное содержимое этого файла, вы обычно увидите ref: refs/heads/master
и тому подобное. (В режиме «отсоединенный HEAD» вместо этого вы увидите необработанный SHA-1.) Есть команды низкого уровня git, которые будут обновлять HEAD
, не делая ничего другого.
Однако большинство людей в основном переключают ветви с помощью git checkout
, что, помимо правильного пути :-), чтобы сделать это, имеет встроенный ряд защит. В основном, он откажется переключать ветви, если у вас есть дерево или «индекс» (AKA-кеш), которые будут потеряны таким коммутатором. Допустим, вы находитесь на ветке A
, и вы просите переключиться на ветвь B
. Процесс проверки должен:
- получить список всех файлов, которые существуют в наконечнике фиксации филиала
A
- получить список всех файлов, которые существуют в наконечнике фиксации филиала
B
- для файлов первый список, который не находится во втором, удалите эти файлы из файла work-dir
- для файлов во втором списке, которые не находятся в первом, добавьте эти файлы в рабочий каталог
- для файлов, находящихся в оба, замените содержимое рабочего каталога, если (и только если) файлы различаются г
Кроме того, выезд осуществляется «писать через» кэш: если файл F
отличается A
и B
содержимое версии B
сначала должны быть скопированы в индексную/кэш, а затем записывается в рабочий каталог.
Если вы устроили (с git add
) некоторой модификацией в файл F
, или у Вас есть ип-ступенчатая модификация F
в вашем рабочем каталоге, этот процесс проверки будет перезаписывать те поставил или отменить изменения в постановке, так git checkout
остановок с сообщением об ошибке. Если файл F
должен быть удален, это также приведет к перезаписи (или, точнее, удалению) ваших изменений, поэтому снова остановится checkout
.
С другой стороны, если файл F
это то же самое в обоих фиксаций, то checkout
может продолжаться: он просто оставляет непредоставленные совершенные изменения в постановке или unstaged. Вот почему вы можете иногда, но не всегда, просто git checkout
филиал, над которым вы хотели работать.
"заначка" Git (как в git stash
), как вы видели, независимо от ветвей. Ключевая концепция здесь заключается в том, что каждый тайник - вы можете иметь более одного активного за раз - на самом деле совершить (или, точнее, набор коммитов: два или три, в зависимости от того, что вы застреваете). Прежде чем вы возражаете, что фиксации сделаны на ветках, мы должны сделать еще пару различий. В частности, слово «ветвь» означает две или три разные вещи, в git.
Обязательно всегда (обязательно) переходить в «фиксацию графа», так как график - это просто вещь, образованная всеми коммитами и их ребрами. В той степени, в которой слово «ветвь» означает «часть графа фиксации», эти фиксации запятой находятся на ветвях. Но слово «ветвь» также относится к именам, которые идентифицируют ветвь tip commit, и здесь эти фиксации кошелька не продвигают ответвление. (См this post, также Jubobs, для получения более подробной информации о нескольких значениях «ветви».)
Команда git stash
смотрит на текущий индекс/кэш и работа дерева состояние, и делает новые коммиты из них если - это «если» оказывается весьма важным - , если у них есть сохраненные поэтапные или неустановленные изменения. Один из этих новых коммитов (из которых можно найти другие) сохраняется под специальным ссылочным именем stash
. Однако ни одна из новых коммитов не добавляется в текущую ветку, поэтому они не находятся в какой-либо именованной ветке. В этом смысле они независимы от текущей ветви, но поскольку они совершают транзакции, у них есть идентификаторы фиксации родителя, и в этом конкретном смысле они привязаны непосредственно к фиксации, которая действовала, когда был выполнен save
.
Что это означает для вас, конечный пользователь, часто «ничего»: вам, вероятно, все равно, и вам не все равно. Тем не менее, если вы когда-либо использовали git stash branch
, чтобы превратить тайник в ветвь, это означает, что новая ветка будет откидываться от фиксации, прикрепленной к ней. (Это, как выясняется, как правило, именно то, что вы хотите.)
Один из рисков с определением псевдонима или макрос, который делает git stash save && git checkout ... && git stash pop
является то, что первый шаг, git stash save
, ничего не может сделать.
Если он ничего не делает, если он не нажимает новый штамп на «стежок стека», то он все равно преуспеет, и ваш псевдоним-макрос продолжит проверку другой ветви, а затем (попробуйте) вытащите стопку из стека.
Если в этом стеке есть другой (другой) штамп, который вы хотели использовать где-то в другом месте, ну, вы просто попытались вставить его в ветку, на которую вы только что переключились.
Обратите внимание, что есть два сложены «если» S здесь, два условия, которые должны соблюдаться для этой конкретной ошибки укусить:
- вам нужно не иметь ничего копить и
- вам нужно есть некоторые существующие кошельки вы не хотите выскочил.
Один из способов решения этой проблемы - использовать скрипт, а не просто простой псевдоним git, для выполнения последовательности ветвления-переключателя-с-stash.В сценарии вы запускаете git stash
, как обычно, но до и после тайника вы проверяете SHA-1, что ссылка stash
разрешает, если таковая имеется. Если это изменится, то git stash save
сохранил что-то, поэтому есть что поп, и вы можете продолжить последовательность выписки и поп-музыки. Если это не изменится - если не было закладок до и после, или если прикрытие вверху стека все еще находится в верхней части стека, тогда нечего делать, и вы должны просто сделать чек.
Есть еще одна ошибка, которая может вас укусить; см. this answer на несколько иной вопрос, который включает в себя немного кода оболочки, выражающего вышеуказанный «pop», только если save
фактически нажал что-то «правило».
* Если я хочу переключить ветви, он автоматически запустит мою рабочую копию, прежде чем переключиться на новую ветку. * Нет! Если у вас есть незафиксированные изменения, конфликтующие с веткой, которую вы проверяете, Git не позволит вам это сделать. Вам нужно будет их вручную «вручную»; Git не делает это автоматически для вас. – Jubobs
Хорошо бы знать, что я не просто что-то пропустил. Я предполагаю, что всплывающее окно из SourceTree, спрашивающее, хотите ли вы отменить локальные изменения, также должно выступать в качестве напоминания о блокировке их перед переключением. – Mathieson
Я считаю, что у вас будет гораздо лучший опыт, если вы используете Git из командной строки, но это только мое мнение. В частности, я не уверен, позволяет ли SourceTree определять псевдонимы/макросы. – Jubobs