Является ли использование Git Stash в качестве рабочего процесса антипаттерном?

25

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

Я также видел, как некоторые люди в нашей команде использовали рабочий процесс, основанный на git stash . Рабочий процесс выглядит примерно так:

  • Работа на основной ветке (вроде master)
  • Делайте коммиты по ходу дела
  • Если вам нужно получить изменения или переключить ветки, перенесите ваши незафиксированные изменения в тайник
  • Как только ваше обновление будет сделано, вытолкните изменения из тайника.

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

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

Будет ли использование git stash регулярно считаться анти-паттерном? Если да, то какие конкретные проблемы могут возникнуть? Если нет, каковы преимущества?

joshin4colours
источник
2
Вы могли бы попытаться спросить своих коллег, были ли у них какие-либо проблемы с рабочим процессом. Если нет, то я не считаю это вредным.
AlexFoxGill
@AlexG Это верный момент. Я задаю вопрос здесь, чтобы увидеть, есть ли какие-то "ошибки", найденные людьми.
joshin4colours
3
Если я правильно понимаю ... If you need to get changes or switch branches, push your uncommitted changes onto the stash- это именно то, что тайник для.
3
@MichaelT Мой местный филиал позволяет все. Безоговорочно.
Маартин
2
Мой шаблон: -> не использовать git stash -> использовать функциональные ветви -> сохранить незавершенное производство с сообщением фиксации «wip». -> интерактивная перебазировка на ветке, чтобы раздавить вайпы в один значимый коммит, но только для ваших локальных, невыпущенных изменений. -> push to remote -> объединиться с master (и push) в соответствии с вашим рабочим процессом git.
Майкл Даррант

Ответы:

31

Из Git SCM Book :

Часто, когда вы работали над частью своего проекта, все в беспорядочном состоянии, и вы хотите немного переключить ветки, чтобы работать над чем-то другим. Проблема в том, что вы не хотите делать коммит наполовину проделанной работы, чтобы потом вернуться к этому вопросу. Ответом на этот вопрос является команда git stash.

Stashing берет грязное состояние вашего рабочего каталога, то есть ваших измененных отслеживаемых файлов и поэтапных изменений, и сохраняет его в стек незавершенных изменений, которые вы можете повторно применить в любое время.

Учитывая это описание, я бы сказал, что это Anti Pattern. Чрезмерно упрощенным объяснением Git Stash будет то, что это «вырезать и вставить» управления исходным кодом. Вы берете кучу измененных файлов, «прячете» их в ручке для хранения вне обычного рабочего процесса ветвления в Git, а затем позднее применяете эти изменения к другой ветви.

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

Это действительно сводится к этому:

Вы можете вбить винт в стену, и он удержит изображение, но вы должны использовать отвертку. Не используйте молоток, когда отвертка сидит рядом с вами.

О совершении "сломанного" кода

Хотя следующее мнение, я пришел к этому мнению из опыта.

Фиксируйте рано, и совершайте часто. Зафиксируйте столько битого кода, сколько захотите. Просматривайте свою локальную историю коммитов как «точки сохранения», пока вы что-то взламываете. Как только вы выполнили логическую часть работы, сделайте коммит. Конечно , это может нарушить все, но это не имеет значения до тех пор , пока вы не толкать эти коммиты. Перед тем как нажать, перебазировать и раздавить ваши коммиты.

  1. Создать новую ветку
  2. Взломать взломать взломать
  3. Зафиксируйте испорченный код
  4. Отполировать код и заставить его работать
  5. Зафиксируйте рабочий код
  6. Ребаз и Сквош
  7. Тест
  8. Нажмите, когда тесты проходят

Для OP эта ветка сообщений ядра Linux может представлять интерес, потому что это звучит так, как будто некоторые члены команды OP используют Git аналогичным образом.

@RibaldEddie сказал в комментарии ниже:

Прежде всего, тайник не находится вне «ветвящегося рабочего процесса», так как тайник - это просто еще одна ветвь.

(рискуя навлечь на себя гнев многих людей)

Линус сказал:

С помощью «git stash» вы также можете иметь несколько разных спрятанных вещей, но они не стоят в очереди друг на друга - это просто случайные независимые патчи, которые вы спрятали, потому что они были неудобны в какой-то момент.

Я думаю, что @RibaldEddie пытается сказать, что вы можете использовать его git stashв рабочем потоке ветви функций - и это правда. git stashПроблема не в том, что это проблема. Это комбинация совершения, чтобы освоить и использовать git stash. Это анти паттерн.

Разъяснение git rebase

Из комментария @ RibaldEddie:

Перебазирование намного больше похоже на копирование и еще хуже изменяет фиксированную историю.

(Акцент мой)

Изменение истории коммитов не так уж и плохо, если это локальная история коммитов . Если вы перебазируете коммиты, которые вы уже выдвинули, вы, по сути, осиротите любого, кто использует вашу ветку Это плохо.

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

Есть еще один интересный поток ядра Linux по чистой истории коммитов .

Опять от Линуса:

Я хочу чистую историю, но это действительно означает (а) чистую и (б) историю.

Люди могут (и, вероятно, должны) перебазировать свои частные деревья (свою работу). Это уборка . Но никогда код других людей. Это "уничтожить историю"

Так что часть истории довольно проста. Есть только одно основное правило и одно незначительное уточнение:

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

    Обратите внимание, что это действительно история других народов , а не кодекс других народов . Если они отправили вам материал в виде патча по электронной почте, и вы применили его с помощью «git am -s», то это их код, но это ваша история.

    Таким образом, вы можете сходить с ума от «git rebase», даже если вы не писали код, если сам коммит является вашим личным.

  • Небольшое уточнение к правилу: как только вы опубликовали свою историю на каком-то общедоступном сайте, ее могут использовать другие люди, и теперь она явно больше не является вашей личной историей.

    Таким образом, небольшое пояснение на самом деле заключается в том, что речь идет не только о «вашем коммите», но и о том, что он является приватным для вашего дерева, и вы еще не выдвинули его и не объявили об этом.

...

Теперь «чистая» часть немного более тонкая, хотя первые правила довольно очевидны и просты:

  • Держите свою историю читабельной

    Некоторые люди делают это, просто сначала разбираясь со своими мыслями, а не совершая ошибок. но это очень редко, и для остальных из нас мы используем «git rebase» и т. д., пока работаем над нашими проблемами.

    Так что "git rebase" не ошибается. Но это правильно, только если это ВАШЕ СОБСТВЕННОЕ ЧАСТНОЕ дерево.

  • Не выставляй свое дерьмо.

    Это означает: если вы все еще находитесь в фазе «git rebase», вы ее не выталкиваете. Если он не готов, вы отправляете патчи или используете частные git-деревья (просто как «замену серии патчей»), о которых вы не говорите широкой публике.

(акцент мой)

Вывод

В конце концов, у ОП есть разработчики, которые делают это:

git checkout master
(edit files)
git commit -am "..."
(edit files)
git stash
git pull
git stash (pop|apply)

Здесь есть две проблемы:

  1. Разработчики стремятся освоить. Закрой это немедленно. Действительно, это самая большая проблема.
  2. Разработчики постоянно используя git stashи git pullна мастере , когда они должны использовать полнометражную ветвь.

Нет ничего плохого в использовании git stash- особенно перед извлечением - но использование git stashтаким способом является антишаблоном, когда в Git есть лучшие рабочие процессы.

Их использование git stashкрасной сельди. Это не проблема. Обязательство освоить это проблема.

Грег Бургхардт
источник
4
Вау, это не правильно. Прежде всего, тайник не находится вне «ветвящегося рабочего процесса», так как тайник - это просто еще одна ветвь. Идея, что это рабочий процесс копирования-вставки, не имеет смысла. Перебазирование намного больше похоже на копирование и еще хуже изменяет фиксированную историю. Наконец, ваш рабочий процесс полностью бесполезен, если вам нужно поделиться работой с коллегами, поскольку он разваливается, как только вы вносите изменения. То, как это имеет шесть голосов, является ошеломляющим.
Рибальд Эдди
8
@RibaldEddie: Нет ничего плохого в том, чтобы перебирать и переписывать историю коммитов, если это локальная история коммитов. Как только вы нажмете эти коммиты, ваш комментарий будет правильным, но перечитайте мой ответ. Он говорит: «Перед тем, как толкнуть, переделайте и раздавите свои коммиты». Это локальная история коммитов, которая полностью находится под вашим контролем.
Грег Бургхардт
1
@RibaldEddie: я уточнил свой ответ. Это действительно нужно было убрать.
Грег Бургхардт
Я предоставлю немного больше контекста в своем ответе.
Рибальд Эдди
Посмотрите мой ответ ниже - хотя принятие мастериты - это анти-паттерн, это не настоящая проблема.
Рибальд Эдди
7

Лично я использую только stashдля коротких, неожиданных перерывов, например, когда кто-то задает вопрос, требующий перехода на другую ветку. Я делаю это, потому что я забыл о тайниках раньше, тогда они не будут применяться чисто. Регулярные коммиты в ветвях объектов гораздо сложнее забыть и легче объединить, поэтому теперь я склонен просто делать прерванный коммит, а затем делать git reset HEAD~1или делать ребаз, если я не хочу сохранять его позже.

Однако отличительной особенностью распределенного контроля версий является то, что люди могут использовать предпочтительный рабочий процесс в своих собственных репозиториях, если общие репозитории соответствуют стандартам. Я хотел бы убедиться, что люди не просто используют stashрабочий процесс, потому что у них нет достаточного обучения или осведомленности об альтернативах, но если они по-прежнему выбирают рабочий процесс, который вы считаете неоптимальным, я бы оставил это так.

Карл Билефельдт
источник
1

Я думаю, что часть вашего вопроса, которая является анти-паттерном, - это использование одного общего мастера ветки . Однако, если вы добавите разрабатываемую ветвь в дополнение к основной ветке, а затем будете использовать стэши для работы со своими собственными переключателями контекста в разрабатываемой ветке, это не будет анти-паттерном, и это очень близко отражает часть рабочего процесса. описывают такие организации, как Etsy и Facebook.

Это сказанное, ответ @Greg Burghardt выше, слишком благоприятен для так называемого рабочего потока git-потока или функциональной ветви. Раньше я выступал за подобную стратегию, но, поняв, что она добавляет ненужную сложность и создает ложное чувство безопасности, я больше не делаю. Это также пережиток времен нецентрализованных систем контроля версий, таких как Subversion.

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

Команда rebase, однако, может повредить историю ветвления, когда в одном из воспроизведенных коммитов возникает конфликт слияния. От http://ryantablada.com/post/the-dangers-of-rebasing-a-branch

Остальная часть перебазирования проходит гладко, тесты, кажется, все проходят. PR сделан.

А затем пишется еще немного кода, который опирается на свойство commentsForAllPosts, и все нарушается. Но к кому мы обращаемся за помощью? git blame показывает, что строка кода была написана только инженером на стороне сервера, и он вскидывает руки.

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

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

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

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

Фундаментальный анти-паттерн, который я вижу, связан не с ветками и тайниками, а скорее с типами проблем, о которых некоторые очень умные люди уже давно говорят: уверены ли вы в своем коде, используя модульные тесты и хорошая архитектура? Можете ли вы вносить постепенные изменения в свой код так, чтобы ваши разработчики могли легко рассуждать об изменениях и понимать, что изменится? Ваши разработчики хотя бы раз пробовали новый код, чтобы посмотреть, действительно ли он работает? (Да, я видел это раньше).

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

RibaldEddie
источник
2
Ваш комментарий о перебазировании проблем с разрешением слияния не соответствует действительности. Перебазирование - это то же самое, что и фактическое слияние. Git просто объединяет коммиты под капотом. Перебазировка и разрешение конфликта слияния не повредит истории коммитов. Перебазирование и неправильное разрешение конфликта слияния наносит ущерб вещам, что так же, как и при обычном слиянии. Я должен согласиться с тем, что ветки функций увеличивают сложность, но это может быть необходимой сложностью, если разработчики должны манипулировать несколькими несвязанными изменениями.
Грег Бургхардт
Так вы говорите, что слияния могут уничтожить историю ?! Похоже, это просто больше оправдания для того, чтобы избежать слишком большого количества веток!
Рибальд Эдди
1
Слияния не могут уничтожить историю. Я думаю, что вы можете неправильно понять, как происходит перебазировка и слияние. Когда возникает конфликт слияния, его должен решать человек. Если человек разрешает это неправильно, вы не можете винить Git (или SVN, или CVS, или {вставить контроль источника здесь}).
Грег Бургхардт
Теперь то, что вы говорите, противоречит тому, что вы сказали раньше. Вы читали статью, из которой я цитировал? Вы понимаете контекст, в котором перебазировка потеряет историю?
Рибальд Эдди
1
Я прочитал статью. «В Keen мы стараемся продвигать наш код после почти каждого коммита». Это звучит безумно для меня. Либо они делают слишком большие коммиты, либо выталкивают код, который еще не готов. Если вы немедленно сделаете все свои коммиты публичными, то да, перебазировка вызовет проблемы. Это принцип «Доктор, доктор, мне больно, когда я так поступаю».
Kyralessa
1

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

Рабочий процесс «каждый принимает и продвигает к основному каналу» - это тот процесс, который работает вполне разумно, когда нет никаких рискованных изменений. Его часто используют в средах svn, где есть один авторитетный центральный сервер с кодом.

Git, однако, связывает покончить с одним центральным сервером. Имея все разработчики делают commit, pull(или , rebaseесли вы в этом), pushвсе время может сделать большой беспорядок.

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

Для этого git stashбудет правильным инструментом для использования.

Однако в основе этого рабочего процесса лежит большая проблема. Это то, что все роли ветвей контроля версий находятся в одной ветке. Mainline, разработка, обслуживание, накопление и упаковка - все на Master. Это проблема (См. Расширенные стратегии ветвления SCM для получения дополнительной информации об этом подходе к ветвям)

И да, вы кричали, что это не очень хороший рабочий процесс, и с ним есть проблемы. Однако проблема не в инструменте git stash. Проблема заключается в отсутствии четкого ветвления для ролей или несовместимых политик .

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

git stashне анти паттерн. Использование git stashв качестве альтернативы ветвлению, когда все подчиняются Мастеру, является анти-паттерном, но не из-за git stash.

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

Сообщество
источник