Как мне открыть git stash, не вызывая авто-слияние?

Краткая версия этого вопроса такова: как я могу git stash без автоматического слияния?


Теперь для более длинной версии...

Рассмотрим следующий игрушечный пример альтернативы git stash... + git pull... + git pop.

Во-первых, git status показывает, что единственное изменение в рабочем каталоге - это какой-то отслеживаемый файл foo.

# On branch 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:   foo
#
no changes added to commit (use "git add" and/or "git commit -a")

Теперь, чтобы переустановить рабочий каталог в чистое состояние, в качестве предварительного условия для запуска git pull, я временно переименую измененный файл foo (на какое-то непроверенное имя) и восстановлю версию foo в HEAD...

% mv foo foo.$(date +%Y%m%dT%H%M%S)
% git checkout foo
% git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   foo.20130508T110014
nothing added to commit but untracked files present (use "git add" to track)

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

% git pull

Наконец, я восстанавливаю временно переименованный foo.

% mv foo.20130508T110014 foo

... и я вернулся к

% git status
# On branch 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:   foo
#

Это "моральный эквивалент" git stash save + git pull + git stash pop, за исключением того, что первый, а не последний не застрахован от "конфликтов слияния", как этот:

% git stash save 'WIP'
% git pull
% git stash pop
Auto-merging foo
CONFLICT (content): Merge conflict in foo

Как мне повторить приведенную выше последовательность rename-checkout-pull-rename, используя git stash save +... + git stash pop, не вызывая автоматического слияния?

Кстати, подпрограмма rename-checkout-...-rename более точно отражает то, что я ожидаю от команды stash. Другими словами: сохраните состояние моего рабочего каталога сейчас и замените его позже. Там нет "слияния" в этой картине.

Ответ 1

Я запоздало понял, что git уже обеспечивает чрезвычайно простое решение проблемы, которая мотивировала этот вопрос (а именно, автоматическое слияние с возможностью перевода репозитория в "незакрытое состояние").

Все, что нужно сделать, это использовать

git stash branch <branchname> [<stash>]

вместо git stash pop (или git stash apply).

Это создает тайник таким образом, чтобы гарантировать отсутствие конфликтов.

Ответ 2

stash объединяется, как только это работает.

Вы можете добиться слияния без слияния с помощью write-tree read-tree и checkout-index. Здесь приведен пример для создания нетронутой тестовой среды.

Чтобы просто применить принудительный кэш без слияния, вы можете, например,

git read-tree stash^{tree}
git checkout-index -af

Ответ 3

ОК, перейдя в нечто вроде этого:

% git stash pop
Auto-merging foo
CONFLICT (content): Merge conflict in foo
Auto-merging bar
CONFLICT (content): Merge conflict in bar
Auto-merging baz
CONFLICT (content): Merge conflict in baz
...

# $#@?!?!%$!*@#...

... лучшим решением, которое мне удалось придумать, является ответ на это:

% git checkout --theirs $(git diff --name-only --diff-filter=U)
% git reset
% git stash drop

(На основе этого ответа.)

Ответ 4

Тот факт, что вы видите конфликт слияния, означает, что произошел сбой в файле foo, который вы вытащили с сервера. Таким образом, копирование файла и его перемещение полностью уничтожит все изменения из репо в файле foo. Если вы сделаете это, другой человек, совершивший изменения, будет foo будет ненавидеть вас.

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

Если вы просто хотите узнать, что такое изменение в ветке, вы можете использовать git fetch вместо git pull и сравнить свой текущий код с этим. Или, если вы не хотите объединять свои изменения сейчас, подумайте о работе в отдельной ветке или не потяните, пока не будете готовы к объединению.