Может ли «git pull» автоматически спрятать и выдать ожидающие изменения?


122

Я знаю, как это решить:

user@host$ git pull
Updating 9386059..6e3ffde
error: Your local changes to the following files would be overwritten by merge:
    foo.bar
Please, commit your changes or stash them before you can merge.
Aborting

Но разве нет способа позволить git pullмне танцевать stashи popтанцевать для меня?

Если у этой команды другое имя, ничего страшного.

Создание псевдонима оболочки для git stash; git pull; git stash pop- это решение, но я ищу лучшее решение.


а как насчет псевдонима git ?
Яois

20
git stash; git pull; git stash popПрограммный запуск опасен, потому что, если нечего спрятать, операция git stashбудет невозможна, но git stash popвыскочит последний тайник (если есть), что почти наверняка не то, что вам нужно. У пользователя torek есть отличный пост об этом на Stack Overflow, но я не могу его найти ...
jub0bs


1
@guettli Я не имел в виду, что ваш вопрос дублирует, я просто отвечал на комментарий Джубобса.
VonC

2
В качестве следующего шага операция должна быть успешной только в том случае, если тайник может быть аккуратно применен после вытягивания. Если есть конфликты, вся операция терпит неудачу атомарно, так что дерево не изменяется. Это то, что я хотел бы сделать: либо удалить изменения с моими объединенными локальными, либо выйти из строя с ошибкой и позволить мне вручную решить, что делать дальше. Возможна ли такая транзакция git?
Эд Авис

Ответы:


185

Для Git 2.6+ (выпущен 28 сентября 2015 г.)

только git config интересующая настройка:

rebase.autoStash

(Git 2.27, Q2 2020, теперь у вас тоже есть merge.autostash, см. ниже)

Если задано значение true, автоматически создавать временное хранилище перед началом операции и применять его после завершения операции.
Это означает, что вы можете запустить rebase на грязном рабочем дереве.

Однако используйте с осторожностью: последнее приложение тайника после успешной перебазировки может привести к нетривиальным конфликтам. По умолчанию - false.

объедините это с:

pull.rebase

Если установлено значение true, перебазировать ветки поверх выбранной ветки вместо слияния ветки по умолчанию с удаленного по умолчанию при запуске «git pull».

git config pull.rebase true
git config rebase.autoStash true

Этого хватило бы, чтобы простая git pullработала даже на грязном дереве.
В этом случае псевдоним не нужен.


См. Commit 53c76dc (4 июля 2015 г.) Кевина Даудта ( Ikke) .
(Объединено Junio ​​C Hamano - gitster- в фиксации e69b408 , 17 августа 2015 г.)

pull: разрешить грязное дерево при rebase.autostashвключении

rebase научился прятать изменения, когда он встречает грязное дерево работы, но git pull --rebaseне делает этого.

Проверяйте, загрязнено ли рабочее дерево, только когда rebase.autostashон не включен.


Примечание: если вы хотите тянуть без autostash (даже если rebase.autoStash trueон установлен), у вас с git 2.9 (июнь 2016 г.) есть:

 pull --rebase --no-autostash

См. Фиксацию 450dd1d , фиксацию 1662297 , фиксацию 44a59ff , фиксацию 5c82bcd , фиксацию 6ddc97c , фиксацию eff960b , фиксацию efa195d (2 апреля 2016 г.) и фиксацию f66398e , фиксацию c48d73b (21 марта 2016 г.) Мехул Джайн ( mehul2029) .
(Объединено Junio ​​C Hamano - gitster- в коммите 7c137bb , 13 апреля 2016 г.)

В частности, коммит f66398e включает:

pull --rebase: добавить --[no-]autostashфлаг

Если rebase.autoStashпеременная конфигурации установлена, невозможно изменить ее для " git pull --rebase" из командной строки.

Обучает " git pull --rebase" --[no-]autostashфлаг командной строки, который отменяет текущее значение rebase.autoStash, если он установлен. Как " git rebase" понимает --[no-]autostashопцию, это просто вопрос передачи опции базовому " git rebase" при git pull --rebaseвызове "".


Предупреждение: до Git 2.14 (3 квартал 2017 г.) " git pull --rebase --autostash" не сохранялась автоматически при быстрой пересылке локальной истории в вышестоящий.

См. Commit f15e7cf (01 июня 2017 г.) Тайлера Брейзера ( tylerbrazier) .
(Объединено Junio ​​C Hamano - gitster- в коммите 35898ea , 5 июня 2017 г.)

pull: ff --rebase --autostashработает в грязном репо

Когда git pull --rebase --autostashв грязном репозитории произошла перемотка вперед, ничего не сохранялось автоматически, и извлечение не удавалось.
Это произошло из-за ярлыка, позволяющего избежать выполнения перебазирования при быстрой перемотке вперед, но автостэш игнорируется в этом кодовом пути.


Обновление: Мариуш Павельски задает в комментариях интересный вопрос:

Итак, все пишут о том, autostashкогда вы делаете rebase (или pull --rebase).

Но никто не думает об автостэшировании, когда вы делаете обычное извлечение со слиянием .
Значит, для этого нет автоматического переключателя? Или я чего-то упускаю? Я предпочитаю делать, git pull --rebaseно OP спросил о " стандартном " git pull

Ответ:

Исходный поток обсуждать эту autostash функцию, она была реализована изначально как для git pull(слияния) и git pull --rebase.

Но ... Junio ​​C Hamano (сопровождающий Git) заметил, что:

Если бы это pull-mergeбыло что-то, что вызвало бы "раздражение", вызвавшее эту тему, по определению, локальное изменение перекрывается с объединением, и этот внутренний "всплывающий тайник" коснется путей, которых коснулось объединение, и, вероятно, не приведет к "Отброшено" "но оставьте дальнейшие конфликты для разрешения.

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

Уравнение для «pull-rebase» несколько иное, так как «rebase» настаивает на том, чтобы вы начали с чистого рабочего дерева, поэтому раздражение «скачать, а затем остановиться» кажется еще большим. У меня есть подозрение, что ослабление, которое может быть более продуктивным решением реальной проблемы.

Итак, что касается классического пул-слияния, лучше:

побудите пользователя подумать о характере незавершенного производства в рабочем дереве перед запуском " git pull" .
Это слишком сложный зверь, который может мешать тому, что делают другие, или это банальное изменение, которое он может спрятать и вернуть обратно?

Если первое, ему будет гораздо лучше сделать " checkout -b", продолжайте работать до тех пор, пока локальное изменение не приобретет несколько лучшую форму и не "зафиксирует", прежде чем переходить к исходной ветке.

В последнем случае ему лучше сделать:

  • " git pull",
  • обнаружив конфликт, запустите
    • git stash,
    • git merge FETCH_HEAD и
    • git stash pop

При этом с Git 2.27 (второй квартал 2020 г.) " git pull" научился предупреждать, когда pull.rebaseконфигурация не существует, и ни одна из них --[no-]rebaseне --ff-onlyзадана (что приведет к слиянию).

См. Commit d18c950 (10 марта 2020 г.) от Alex Henrie ( alexhenrie) .
(Объединено Junio ​​C Hamano - gitster- в коммите 1c56d6f , 27 марта 2020 г.)

pull: предупреждать, если пользователь не сказал, перебазировать или объединить

Подписано: Алекс Хенри

Часто начинающие пользователи Git забывают сказать « pull --rebase» и в конечном итоге получают ненужное слияние из восходящего потока.

Обычно они хотят либо " pull --rebase" в более простых случаях, либо " pull --ff-only" обновить копию основных ветвей интеграции и отдельно перенастроить свою работу. Переменная конфигурации существует , чтобы помочь им в более простых случаях, но не существует никакого механизма , чтобы эти пользователи знают об этом.
pull.rebase

Выдавать предупреждающее сообщение, если --[no-]rebaseв командной строке не pull.rebaseуказаны параметры и переменная конфигурации.
Это доставит неудобства тем, кто никогда не хочет " pull --rebase", кому не приходилось делать ничего особенного, но стоимость неудобств оплачивается только один раз на пользователя, что должно быть разумной стоимостью, чтобы помочь ряду новых пользователей.


В Git 2.27 (второй квартал 2020 г.) " git merge" изучает параметр " --autostash" и новый merge.autostashпараметр.

См совершать d9f15d3 , совершать f8a1785 , совершают a03b555 , совершают 804fe31 , совершают 12b6e13 , совершают 0dd562e , совершают 0816f1d , совершают 9bb3dea , совершают 4d4bc15 , совершают b309a97 , совершают f213f06 , совершают 86ed00a , совершают facca7f , совершают be1bb60 , совершают efcf6cf , совершают c20de8b , совершить bfa50c2 , фиксация 3442c3d , фиксация 5b2f6d9 (7 апреля 2020 г.), фиксация 65c425a(4 апреля 2020 г.) и фиксация fd6852c , фиксация 805d9ea (21 марта 2020 г.) Дентоном Лю ( Denton-L) .
(Объединено Junio ​​C Hamano - gitster- в фиксации bf10200 , 29 апреля 2020 г.)

pull: pass --autostash для слияния

Подписано: Дентон Лю

Раньше --autostashработал только с git pull --rebase.

Однако в последнем патче слияние --autostashтакже изучалось, поэтому нет причин, по которым у нас больше нет этого ограничения.
Научите pull to pass --autostashдля слияния, как это было для rebase.

И:

rebase: использовать apply_autostash()из Sequencer.c

Подписано: Дентон Лю

apply_autostash()Функция builtin/rebase.cподобна достаточно , чтобы apply_autostash()функции в sequencer.cтом , что они почти взаимозаменяемы, для типа Arg они принимают за исключением. Сделайте sequencer.cверсию extern и используйте ее в rebase.

Версия rebase была представлена ​​в 6defce2b02 («builtin rebase: support --autostashoption», 2018-09-04, Git v2.20.0-rc0 - слияние указано в пакете №8 ) как часть преобразования оболочки в C.
Он решил продублировать функцию, потому что в то время был еще один незавершенный проект по преобразованию интерактивной перебазировки из оболочки в C, и они не хотели конфликтовать с ними из-за рефакторинга sequencer.cверсии apply_autostash().
Поскольку оба усилия уже давно сделаны, мы можем свободно объединить их вместе.


В версии 2.4.2 это еще не реализовано. Возможно, когда-нибудь. rebase.autoStashприменяется только при использовании rebase. pull.rebaseприменяется только при использовании pull.
Randal Schwartz

«Этого было бы достаточно, чтобы простой git pull работал даже в грязном дереве». Как прокомментировал Рэндал, это еще не так. Текущий мастер pull.c все еще выбирает die_on_unclean_work_tree.
Прадхан

1
@Pradhan Я согласен. Реализация только что получила мастерскую сегодня утром и должна быть готова к git 2.6. Я отредактировал ответ, чтобы прояснить это.
VonC

Я подтвердил, что autostash работает с git 2.5.5.
Джошуа Хоблитт,

1
Итак, все пишут о autostash, когда вы делаете rebase(или pull --rebase). Но никто не думает об автостэшировании, когда вы делаете pullслияния нормально . Значит, для этого нет автоматического переключателя? Или я чего-то упускаю? Я предпочитаю делать это, git pull --rebaseно OP спросил о «стандарте»git pull
Мариуш Павельски

41

Чтобы сэкономить несколько секунд для приближающихся исследователей, вот резюме (благодаря @VonC):

git pull --rebase --autostash

6
Дело в том, что после git config pull.rebase trueи git config rebase.autoStash trueвсе, что вам когда-либо понадобится, это git pull. Просто git pull. Других опций не требуется.
VonC

3
Похоже, вам нужен как минимум Git 2.9 для этой --autostashопции. -c rebase.autoStash=trueРаботает в Git 2.6 и далее.
ntc2

15

Как указано в комментарии выше, установка двух значений конфигурации в настоящее время не работает git pull, поскольку конфигурация autostash применяется только к фактическим перемещениям. Эти команды git делают то, что вы хотите:

git fetch
git rebase --autostash FETCH_HEAD

Или установите его как псевдоним:

git config alias.pullr '!git fetch; git rebase --autostash FETCH_HEAD'

Затем сделайте:

git pullr

Конечно, этот псевдоним можно переименовать по желанию.


7

В Git 2.6+ вы можете использовать следующее:

alias gup='git -c rebase.autoStash=true pull --rebase'

Это --rebaseделает ГИТ-тянущего использовать rebaseвместо merge, поэтому настройки / опции , как --ff-onlyне будет применяться.

Я использую псевдоним для извлечения --ff-onlyпо умолчанию ( git pull --ff-only), а затем могу использовать gup(сверху) в случае, если быстрое слияние невозможно или есть спрятанные изменения.


В чем основное различие между git pull --ff-onlyиgit pull pull --rebase --autostash
alper

0

Как вы уже упоминали, это способ сделать это. Вы можете использовать его в псевдониме, чтобы сохранить ввод и использовать ярлык, или вы можете использовать его в одной строке (также может быть псевдонимом)

git stash && git pull --rebase && git stash pop

Он будет делать то же самое, что и вы, но в одной строке (&&), и если вы установите псевдоним, он будет даже короче.

Следующие строки будут отображать входящие / исходящие изменения до того, как вы потянете / нажмете

git log ^master origin/master
git log master ^origin/master

8
Этот подход небезопасен: если нечего припрятать, первая команда ничего не сделает, а затем stash popраспакует некоторые случайные вещи из прошлого.
Джон Цвинк 01

Чтобы быть предельно ясным: даже если git stashничего не хранит, он все равно не «возвращает» код ошибки, поэтому && будет продолжать с git pullи git stash popи вытолкнуть предыдущий тайник. Так что лучше не используйте это, если вы не очень уверены, что он что-то припрятал!
MoonLite
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.