Почему сквош-мерзавец совершает запросы на извлечение?

201

Почему каждый серьезный репозиторий Github, который я выполняю, требует, чтобы я раздавил свои коммиты в один коммит?

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

Это также, кажется, идет вразрез с мантрой «давай рано и часто».

hamstar
источник
1
Для большого репо это экономит много времени и места, когда люди хотят что-то делать с репо.
raptortech97
8
« Это также, кажется, идет вразрез с« мантрой рано и часто коммит ». - Нет, вы делаете коммит рано / часто, но не обязательно хотите связываться с каждым крошечным изменением. И рецензент не хочет их просматривать, это точно.
JensG
7
Не нужно вносить изменения в вопрос, чтобы резюмировать, каков воспринятый ответ. Это место принятых ответов и голосов. Люди могут сделать свои собственные выводы из чтения ответов.
5
Я до сих пор не понимаю, почему возникает желание сдавить коммиты. Я думаю, что есть слишком много минусов, чтобы раздавить почти без плюсов. Это проблема презентации, маскирующаяся под проблему данных.
mkobit
3
Любая полезная аналитика в журнале теряется из-за сквоша. Похоже, разработчик сделал функцию с помощью одного коммита. Также трудно понять, почему существует странный кусок кода. История функции может быть важной, и может многое объяснить, почему код такой, какой он есть. Краткий обзор журнала полезен, но разве его нельзя достичь другим способом?
Тьяарт

Ответы:

158

Так что у вас есть четкая и краткая история Git, которая ясно и легко документирует сделанные изменения и причины, почему.

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

7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
787g8fgf78... hotfix for #5849564648
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

Какой беспорядок!

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

7hgf8978g9... 8483948393 Added new slideshow feature
787g8fgf78... 5849564648 Hotfix for android display issue
9080gf6567... 6589685988 Implemented pop-up to select language

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

Вы хотите совершить рано и часто. Это лучшая практика по многим причинам. Я обнаружил, что это приводит меня к тому, что у меня часто появляются коммиты, которые являются «wip» (незавершенным) или «part A done» или «опечатка, мелкое исправление», где я использую git, чтобы помочь мне работать и дать мне рабочие точки, которые Я могу вернуться к тому, если следующий код не работает, поскольку я прогрессирую, чтобы заставить вещи работать. Однако мне не нужна или не нужна эта история как часть окончательной истории git, поэтому я могу раздавить свои коммиты - но см. Примечания ниже относительно того, что это значит в ветке разработки против master.

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

8754390gf87... Implement feature switches

похоже на «1 часть работы». Либо они существуют, либо нет! Кажется, не имеет смысла разбивать это. Однако опыт показал мне, что (в зависимости от размера и сложности организации) более детальный путь может быть:

fgfd7897899... Add field to database, add indexes and a trigger for the dw group
9458947548g... Add 'backend' code in controller for when id is passed in url.
6256ac24426... Add 'backend' code to make field available for views.
402c476edf6... Add feature to UI

Маленькие кусочки означают более легкие проверки кода, более простое модульное тестирование, лучшую возможность проверки качества, лучшее согласование с принципом единой ответственности и т. Д.

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

  • ваше развитие, например, запросы на получение
  • ваша работа добавлена ​​в основную ветку, например, master

Во время разработки вы делаете «рано и часто» и быстро «одноразовыми» сообщениями. Иногда вы можете захотеть раздавить, например, сдавить в сообщениях wip и todo. В ветке можно сохранять несколько коммитов, которые представляют собой отдельные шаги, которые вы сделали в процессе разработки. Большинство сквошов, которые вы выбираете, должны находиться в пределах этих ветвей функций, пока они находятся в стадии разработки и до слияния с мастером.
При добавлении в ветку mainline вы хотите, чтобы коммиты были краткими и правильно отформатированными в соответствии с существующей историей mainline. Это может включать идентификатор системы Ticket Tracker, например, JIRA, как показано в примерах. Сквошинг здесь на самом деле не применяется, если вы не хотите «свернуть» несколько отдельных коммитов на мастере. Обычно нет.

Использование --no-ffпри слиянии с мастером будет использовать один коммит для слияния, а также сохранит историю (в ветке). Некоторые организации считают это лучшей практикой. Подробнее на https://stackoverflow.com/q/9069061/631619. Вы также увидите практический эффект, git logкогда --no-ffкоммит будет последним коммитом, в верхней части HEAD (когда он только что сделан), тогда как без --no-ffнего может быть дальше в историю, в зависимости от дат и других коммитов.

Майкл Даррант
источник
30
Я полностью не согласен с этой философией. Небольшие регулярные коммиты разбивают задачу на более мелкие и часто дают полезную информацию о том, над чем именно работали, когда линия была изменена. Если у вас небольшие коммиты "WIP", вы должны использовать интерактивную перебазировку, чтобы очистить ее, прежде чем нажимать на нее. Кажется, что раздавливание PR полностью побеждает точку регулярных небольших коммитов ИМХО. Это почти неуважительно по отношению к автору, который приложил усилия для предоставления сообщений журнала с конкретной информацией о коммите, а вы просто выбросили все это.
Еж
6
Интересно. В конце дня я основываю свою «философию» на увиденных работах. Чтобы быть ясным - разбить работу на мелкие части и совершить каждый из них прекрасно, работая над изменениями. Мой опыт показывает, что после слияния этой работы с мастером главное , что, как правило, нужно исследовать, это «что, в сущности, это коммит слияния, который (обычно) вызывал проблемы х ...»
Майкл Даррант
6
Я тоже против сквоша. Вы не должны писать глупые сообщения о коммитах. И в примере (85493g2458 ... Исправлена ​​проблема с показом слайд-шоу в ie). Это было бы намного полезнее, если бы мне пришлось отлаживать связанный с ним код.
Томас Дэвис,
5
К сожалению, такая небрежная и неуместная догма появилась в практике СКМ. Для управления удобочитаемостью истории, а не фиксацией поведения должны использоваться инструменты фильтрации.
cppenrose
4
тревожные тенденции и догмы. Оттавы. Я предпочел бы более основанный на фактах аргумент, представленный более приятным способом. Вы можете оставить / проголосовать другое мнение. В этом смысл общественного голосования
Майкл Даррант
26

Поскольку часто человек, занимающийся пиаром, заботится о сетевом эффекте коммитов «добавленная функция X», а не о «базовых шаблонах, функции исправления ошибок X, функции добавления Y, исправленных опечатках в комментариях, скорректированных параметрах масштабирования данных, hashmap работает лучше, чем список "... уровень детализации

Если вы считаете, что ваши 16 коммитов лучше всего представлены 2 коммитами, а не 1 «Добавлена ​​функция X, перефакторинг Z для использования X», тогда, вероятно, было бы неплохо предложить pr с 2 коммитами, но тогда лучше всего предложить 2 отдельных PR в этом случае (если репо все еще настаивает на одном коммитном PR)

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

Эндрю Хилл
источник
4
Но когда вы делаете сквош коммиты, вы тоже теряете эту историю в своей форке, верно? Почему вы хотите выбросить эту историю?
Hamstar
4
a) если вы хотите сохранить историю в своей ветке, достаточно легко иметь ветку «для слияния» и ветку «dev» (что может быть тем, что вам нужно в любом случае, так как вы можете добавлять новые коммиты в свой основной dev ветвь после того, как вы предложите PR) b) вы все еще сохраняете чистый эффект этих коммитов, это будет только в тех случаях, когда вы хотите отменить или выбрать из подкомпонента pr, что отдельные коммиты будут необходимы , В этом случае вы, вероятно, делаете несколько вещей (например, исправление ошибки X, добавляете функцию Y) в одном PR, и снова может потребоваться несколько PR.
Эндрю Хилл
@AndrewHill какая замечательная концепция! Я хочу представить этот рабочий процесс моей команде, как он работал для вас? Я написал сообщение в блоге об этом , и столкнулся с этим комментарием, исследуя это.
Дрооганс
19

Основная причина того, что я вижу, заключается в следующем:

  • Пользовательский интерфейс GitHub для слияния запросов на выборку в настоящее время (октябрь 2015 г.) не позволяет редактировать первую строку сообщения фиксации, заставляя его Merge pull request #123 from joebloggs/fix-snafoo
  • Пользовательский интерфейс GitHub для просмотра истории коммитов в настоящее время не позволяет вам просматривать историю ветки с --first-parentточки зрения
  • Пользовательский интерфейс GitHub для просмотра вины в файле в настоящее время не позволяет вам просматривать вину файла с --first-parentточки зрения (обратите внимание, что это было исправлено только в Git 2.6.2, поэтому мы могли бы простить GitHub за отсутствие этого доступный)

Поэтому, когда вы объединяете все три вышеперечисленные ситуации, вы получаете ситуацию, когда несокращенные коммиты сливаются с помощью пользовательского интерфейса GitHub.

Ваша история с раздавленными коммитами будет выглядеть примерно так

1256556316... Merge pull request #423 from jrandom/add-slideshows
7hgf8978g9... Added new slideshow feature
56556316ad... Merge pull request #324 from ahacker/fix-android-display
787g8fgf78... Hotfix for android display issue
f56556316e... Merge pull request #28 from somwhere/select-lang-popup
9080gf6567... Implemented pop-up to select language

Тогда как без раздавленных коммитов история будет выглядеть примерно так

1256556316... Merge pull request #423 from jrandom/add-slideshows
7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
56556316ad... Merge pull request #324 from ahacker/fix-android-display
787g8fgf78... hotfix for #5849564648
f56556316e... Merge pull request #28 from somwhere/select-lang-popup
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

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

Например, вы обнаруживаете, что нулевой указатель разыменовывается где-то в файле ... поэтому вы говорите: «Кто это сделал и когда? На какие версии выпуска влияют?». Затем вы переходите к представлению «вина» в пользовательском интерфейсе GitHub и видите, что линия была изменена в789fdfffdf... «о, подождите секунду, в этой строке был изменен отступ, чтобы он соответствовал остальной части кода», так что теперь вам нужно перейти к состоянию дерева для этого файла в родительском коммите и повторно посетить страница с обвинениями ... в конце концов вы находите коммит ... это коммит 6 месяцев назад ... "о **** фактически был в запросе на извлечение и был объединен только вчера, и никто еще не сократил выпуск ... "Черт возьми, люди за объединение коммитов без истории" - это крик, который обычно можно услышать после примерно 2 или 3 экспедиций по археологии кода через GitHub UI

Теперь давайте рассмотрим, как это работает, если вы используете командную строку Git (и супер-удивительный 2.6.2, в котором есть исправление git blame --first-parent)

  • Если бы вы использовали командную строку Git, вы могли бы полностью контролировать сообщение коммита слияния, и, следовательно, коммит слияния мог бы иметь хорошую итоговую строку.

Таким образом, наша история коммитов будет выглядеть

$ git log
1256556316... #423 Added new slideshow feature
7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
56556316ad... #324 Hotfix for android display issue
787g8fgf78... hotfix for #5849564648
f56556316e... #28 Implemented pop-up to select language
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

Но мы также можем сделать

$ git log --first-parent
1256556316... #423 Added new slideshow feature
56556316ad... #324 Hotfix for android display issue
f56556316e... #28 Implemented pop-up to select language

(Другими словами: Git CLI позволяет вам есть свой торт и есть его)

Теперь, когда мы сталкиваемся с проблемой нулевого указателя ... ну, мы просто используем, git blame --first-parent -w dodgy-file.cи нам сразу дается точный коммит, где в основной ветке была введена обратная ссылка нулевого указателя, игнорируя простые изменения пробелов.

Конечно, если вы выполняете слияния с использованием пользовательского интерфейса GitHub, то git log --first-parentэто действительно дерьмо благодаря GitHub, форсирующему первую строку сообщения коммита слияния:

1256556316... Merge pull request #423 from jrandom/add-slideshows
56556316ad... Merge pull request #324 from ahacker/fix-android-display
f56556316e... Merge pull request #28 from somwhere/select-lang-popup

Короче говоря, короткая история:

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

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

Post Script

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

Ну, если вы смотрите историю git, git log --first-parentтогда вы можете просто выбрать коммиты слияния. Большинство людей запутываются в коммитах с вишневым выбором, потому что вы должны указать -m Nопцию, но если вы получили коммит, git log --first-parentто вы знаете, что это первый родитель, которому вы хотите следовать, поэтому он будетgit cherry-pick -m 1 ...

Стивен Коннолли
источник
1
Хороший ответ! Но выбрать диапазон вишни достаточно просто, я не уверен, что в качестве причины я его куплю.
Стигглер
1
@stiggler Я лично не покупаю это как причину, но я видел, что другие цитировали это как причину. ИМХО, инструмент git - это то, что вы хотите, а коммиты на сжатие - это зло ... но я бы сказал, что я сам привел --first-parentсебя в порядок, чтобы выиграть спор против коммитов на сжатие ;-)
Стивен Коннолли
1
Это должен быть принятый ответ. Гораздо меньше догм, и это показывает, что фильтрация истории может быть использована, чтобы «съесть свой пирог и съесть его тоже». Вам не нужно уничтожать историю, чтобы внести ясность в исследования истории git.
ctpenrose
Выбрать вишню будет не так просто, если, раздавив ваши коммиты, вы в итоге сгруппируете множество изменений в разные файлы в один коммит. Я предполагаю, что это сильно варьируется в зависимости от базы кода, какие изменения были внесены, сколько людей сотрудничает и так далее. Я не думаю, что мы можем придумать одно общее правило, которое будет действовать во всех случаях.
Эми Пеллегрини
2

Я согласен с мнением, высказанным в других ответах в этой теме, о показе четкой и краткой истории добавленных функций и исправленных ошибок. Я, однако, хотел бы затронуть еще один аспект, к которому ваш вопрос ускользнул, но прямо не указал. Часть зависания, которую вы можете иметь о некоторых методах работы git, заключается в том, что git позволяет вам переписывать историю, что кажется странным, когда вы знакомитесь с git после использования других форм контроля версий, где такие действия невозможны. Кроме того, это также идет вразрез с общепринятым принципом контроля версий, согласно которому после того, как что-то зафиксировано / возвращено в систему контроля версий, вы сможете вернуться в это состояние независимо от того, какие изменения вы вносите после этой фиксации. Как вы подразумеваете в своем вопросе, это одна из тех ситуаций. Я думаю, что git - отличная система контроля версий; однако, чтобы понять это, вы должны понимать некоторые детали реализации и конструктивные решения, лежащие в основе этого, и в результате у него есть более крутая кривая обучения. Имейте в виду, что git задумывался как распределенная система контроля версий, и это поможет объяснить, почему разработчики разрешают переписывать историю git с помощью коммитов сквоша, являющихся одним из примеров этого.

Фред Томсен
источник
Строго говоря, Git не позволяет вам изменять историю. Коммит объекты неизменны. Изменчивы только указатели веток , и только в этом случае с «принудительным обновлением», которое обычно считается тем, что вы делаете только в целях разработки, а не в основной ветке. Вы всегда можете вернуться к предыдущему состоянию, используя reflog, если только он git gcне был запущен для удаления объектов, на которые нет ссылок .
Джон Пурди,
Вы правы, и я, наверное, должен был упомянуть об этом выше. Однако я бы поспорил, что что-то вроде принудительного толчка или перебазирования коммитов, которые уже были переданы в удаленное репо, квалифицируется как переписывание истории, поскольку порядок и расположение коммитов так же важны, как и сами коммиты.
Фред Томсен
Это верно для данного коммита. В более широкой картине я думаю об интерактивном перебазировании и ответвлении фильтра как об эффективном переписывании истории путем изменения ее состава.
Майкл Даррант
1
Честно говоря, SVN придерживается подхода «каждый коммит - это святое», но когда слияние создает единый коммит с этим слиянием и скрывает внесенные в него ревизии, поэтому создается впечатление, что все слияния SVN «перебазированы». Это не так, вам просто нужно указать команду history, чтобы показать вам объединенные компоненты. Мне нравится этот подход больше всего.
gbjbaanb
1

Из-за перспективы ... Лучшей практикой является, <<issue-management-system>>если возможно, один коммит на одну проблему.

Вы можете иметь столько коммитов, сколько захотите, в своей собственной ветви / репозитории, но это ваша история, относящаяся к тому, что вы делаете сейчас для ВАШЕЙ перспективы ... это не ИСТОРИЯ для всей КОМАНДЫ / ПРОЕКТА или приложения от их перспектива будет сохраняться через несколько месяцев ...

Поэтому, когда вы хотите зафиксировать исправление ошибки или функцию в общем репозитории (этот пример относится к ветке разработки), вы можете сделать это следующим образом:

как быстро перенести вашу ветку

    # set your current branch , make a backup of it , caveat minute precision
    curr_branch=$(git rev-parse --abbrev-ref HEAD); git branch "$curr_branch"--$(date "+%Y%m%d_%H%M"); git branch -a | grep $curr_branch | sort -nr

    # squash all your changes at once 
    git reset $(git merge-base develop $curr_branch)

    # check the modified files to add 
    git status

    # add the modified files dir by dir, or file by file or all as shown
    git add --all 

    # check once again 
    git log --format='%h %ai %an %m%m %s'  | less

    # add the single message of your commit for the stuff you did 
    git commit -m "<<MY-ISSUE-ID>>: add my very important feature"

    # check once again 
    git log --format='%h %ai %an %m%m %s'  | less

    # make a backup once again , use seconds precision if you were too fast ... 
    curr_branch=$(git rev-parse --abbrev-ref HEAD); git branch "$curr_branch"--$(date "+%Y%m%d_%H%M"); git branch -a | grep $curr_branch | sort -nr

    # compare the old backup with the new backup , should not have any differences 
    git diff <<old-backup>>..<<new-backup-branch>>


    # you would have to git push force to your feature branch 
    git push --force 
Йордан Георгиев
источник
это даже не попытка ответить на заданный вопрос, почему Git-комманды на сквош совершают запросы на извлечение? Посмотрите, как ответить
gnat
после попытки объяснения он должен это сделать ...
Йордан Георгиев
Я почему-то не вижу, как добавленное объяснение предлагает что-то существенное по сравнению с высказанными и объясненными в самых популярных ответах, которые были опубликованы несколько лет назад (хотя усилия по улучшению первой редакции приветствуются)
комнат
ключевое слово «перспектива», перспективная концепция значительно упрощает объяснение этого типа проблем в ИТ, например, ваша точка зрения на ответ на этот вопрос уже предоставлена, моя перспектива использует ключевое слово «перспектива». и предоставление практического примера того, как реализовать ту же самую лучшую практику, объясненную с разных точек зрения ...
Йордан Георгиев
1

Я бы посмотрел, станет ли код открытым или нет.

Когда проекты остаются частными:

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

Когда проекты становятся публичными:

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

Винс В.
источник