Чому squash git здійснює запити на тягнення?


199

Чому кожне серйозне репортаж Github, який я роблю, вимагає, щоб я розбив свої зобов’язання в одну комісію?

Я подумав, що журнал git є там, щоб ви могли оглянути всю свою історію і побачити, які саме зміни відбулися там, але при стисканні це витягує його з історії та з’єднує все це в один комітет. У чому сенс?

Це також, здається, суперечить мантрі "вчиняти рано і вчиняти часто".


1
Для великого репо, це економить багато часу та місця, коли люди хочуть зробити що-небудь із репо.
raptortech97

8
" Це також, здається, суперечить" вчиняти рано і вчиняти часто "мантру ". - Ні, ти робиш рано / часто, але не обов'язково хочеш робити PR кожну невелику зміну. І рецензент не хоче їх переглядати, це точно.
JensG

7
Не потрібно вносити правки у запитання, щоб узагальнити, що таке сприйнята відповідь. Це місце прийнятих відповідей та оновлень. Люди можуть робити власні висновки, читаючи відповіді.

5
Я до сих пір не розумію, чому виникає бажання скосити коміти. Я думаю, що занадто багато мінусів для сквашування майже без плюсів. Це випуск презентації, що маскується як випуск даних.
mkobit

3
Будь-яка корисна аналітика на лог втрачається з допомогою кабачків. Тож здається, що розробник зробив функцію за допомогою одного комітету. Також важко зрозуміти, чому існує непарний фрагмент коду. Історія функції може бути важливою і може пояснити, чому код є таким, яким він є. Короткий вигляд журналу корисний, але чи не можна його досягти іншим способом?
Тярт

Відповіді:


158

Так що у вас є чітка і коротка історія git, яка чітко і легко документує зроблені зміни та причини.

Наприклад, типовий журнал git для мене "unšashhed" може виглядати наступним чином:

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

Я думаю, що ви можете бачити сенс стискання комітетів взагалі, і той самий принцип застосовується і до запитів на тягу - Читання історії. Ви також можете додавати до журналу фіксацій, у якому вже є сотні, а то й тисячі комісій, і це допоможе зберегти історію зростання короткою та стислою.

Ви хочете скористатися рано і часто. Це найкраща практика з багатьох причин. Я вважаю, що це призводить до того, що у мене часто трапляються комітети, які є "витримкою" (незавершеною роботою) або "Частиною, виконаною" або "Друкуванням, незначним виправленням", де я використовую git, щоб допомогти мені працювати і дати мені робочі моменти, які Я можу повернутися до, якщо наступний код не працює, коли я прогресую, щоб працювати. Однак мені не потрібна та не хочеться, щоб ця історія була частиною остаточної історії git, тому я можу скоротити свої зобов’язання - але дивіться нижче примітки щодо того, що це означає для галузі розвитку проти майстра.

Якщо є основні основні етапи, які представляють різні робочі етапи, все одно добре мати більше одного комітету на особливість / завдання / помилку. Однак це часто може підкреслити той факт, що квиток, що розробляється, "занадто великий" і його потрібно розбити на більш дрібні шматки, які можуть бути окремими, наприклад:

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

Невеликі шматочки означають простіший огляд коду, простіше тестування одиниць, краща можливість qa, краще узгодження з принципом єдиної відповідальності тощо.

Для практичності, коли насправді робити такі кабачки, в основному є два чіткі етапи, які мають свій власний робочий процес

  • Ваша розробка, наприклад, запити на тягнення
  • Ваша робота додана до основної галузі, наприклад, майстер

Під час свого розвитку ви дотримуєтесь "рано і часто" та швидких "одноразових" повідомлень. Ви можете іноді тут робити сквош, напр., Прибирання в wip і todo повідомляє. В межах філії нормально зберігати кілька комісій, які представляють собою окремі кроки, які ви зробили в процесі розвитку. Більшість сквашек, які ви вирішили зробити, повинні бути в цих галузях, в той час як вони розробляються і перед тим як зливатися для освоєння.
Додаючи до гілки магістралі, ви хочете, щоб коміти були стислими та правильно відформатованими відповідно до існуючої історії основної лінії. Це може включати ідентифікатор системи відстеження квитків, наприклад, JIRA, як показано в прикладах. Сквошинг насправді тут не застосовується, якщо ви не хочете «згорнути» кілька чітких зобов’язань на майстра. Зазвичай ви цього не робите.

Використання --no-ffпід час об'єднання для master використовуватиме один комікт для злиття, а також збереже історію (у філії). Деякі організації вважають це найкращою практикою. Дивіться більше на https://stackoverflow.com/q/9069061/631619 Ви також побачите практичний ефект, git logколи --no-ffкомісія буде останньою коміткою, у верхній частині HEAD (коли це зроблено), тоді як без --no-ffнеї може бути далі в історію, залежно від дати та інших комітетів.


30
Я повністю не згоден з цією філософією. Невеликі регулярні комітети розбивають завдання на більш дрібні завдання і часто дають корисну інформацію про те, над чим саме працювали, коли змінювався рядок. Якщо у вас є невеликі "WIP" програми, вам слід використовувати інтерактивну базу даних, щоб очистити її, перш ніж натискати на них. Сквош-піар, здається, повністю переможе точку регулярних малих комісій IMHO. Автору, який доклав зусиль, щоб подати повідомлення журналу з конкретною інформацією про фіксацію, це майже неповажно, і ви просто викинете все це.
Їжак

6
Цікаво. Зрештою, я базую свою "філософію" на тому, що я бачив. Щоб було зрозуміло - розбивати роботу на невеликі частини та виконувати кожну це чудово, працюючи над зміною. Мій досвід полягав у тому, що після того, як цю роботу об'єднають до головного, головне , що, як правило, вивчається - це «що, в цілому, що це зобов’язання злиття, що, як правило, викликало проблеми x ...
Michael Durrant

6
Я теж проти сквош. Не слід писати повідомлення про дурні вчинки в першу чергу. І в прикладі (85493g2458 ... Виправлена ​​проблема з відображенням слайд-шоу в т. Е.) Це було б набагато корисніше, якби я налагодив код, пов'язаний з ним.
Томас Девіс

5
Прикро, що така необережна і неправильна догма з'явилася в практиці СКМ. Інструменти фільтрації повинні використовуватися для управління читабельністю історії, а не поведінкою.
ctpenrose

4
тривожні тенденції та догми. джоу. Я вважаю за краще більш аргументований аргумент, представлений більш приємним чином. Ви можете опублікувати / проголосувати іншу думку. У цьому сенс голосування громади
Майкл Дюрант

26

Оскільки часто особа, яка витягує PR, піклується про чистий ефект комісій "додана функція X", а не про "базові шаблони, функцію виправлення X, додавання функції Y, фіксованих помилок друку в коментарях, коригування параметрів масштабування даних, хешмак працює краще, ніж список "... рівень деталізації

Якщо ви вважаєте, що ваші 16 комітів найкраще представлені двома позиціями, а не 1 "Додана функція X, перевлаштована Z для використання X", то, ймовірно, добре запропонувати pr з 2 комітами, але тоді, можливо, найкраще запропонувати У цьому випадку є два окремі вказівки (якщо РЕПО все-таки наполягає на однократному примусовому виконанні)

Це не суперечить мантрі "вчиняти рано та вчиняти часто", як у вашому репо, тоді як ви розробляєте, ви все ще маєте детальні деталі, тому у вас є мінімальний шанс втратити роботу, а інші люди можуть переглядати / тягнути / пропонувати PR проти вашої роботи, поки розробляється новий.


4
Але коли ти робиш сквош, ти втрачаєш цю історію і у вилці? Чому ви хочете викинути цю історію?
hamstar

4
а) якщо ви хочете зберегти історію у вашій галузі, досить просто мати гілку "для злиття" та гілку "dev" (що може бути те, що вам все одно потрібно, оскільки ви можете додавати нові зобов’язання до свого головного розробника гілка після того, як ви запропонуєте PR) б) ви все ще зберігаєте чистий ефект цих комісій, це було б лише у випадках, коли ви хочете скасувати або вишневий підкомпонент PR, який потрібен окремим зобов'язанням. . У такому випадку ви, ймовірно, робите кілька речей (наприклад, виправлення помилок X, додайте функцію Y) в одному PR і знову можуть знадобитися декілька PR.
Ендрю Хілл

@AndrewHill яка чудова концепція! Я хочу представити цей робочий процес своїй команді, як це працювало для вас? Я написав про це блог і натрапив на цей коментар, досліджуючи його.
Droogans

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 місяців тому ... "о ****, це може вплинути на користувачів протягом 6 місяців", ви кажете ... ах, але зачекайте, що здійснити насправді був у запиті на виклик, і лише вчора було об'єднано, і ніхто ще не вирізав реліз ... "Чорт за вас, люди за об'єднання комісій без історії розкочування", - це крик, який зазвичай можна почути приблизно через 2 або 3 експедиції археології коду через Користувацький інтерфейс GitHub

Тепер давайте розглянемо, як це працює, якщо ви використовуєте командний рядок 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 немає цих проблем, і ви можете легко вибрати, який саме вид ви хочете бачити, щоб ви могли виявити причину того, чому певна зміна була внесена таким чином (переглянувши історію нерозбірливих комісій), а також перегляньте ефективно стиснуті коміти.

Пост сценарію

Кінцева причина, яку часто цитують для скоєння комбінезонів, полягає в тому, щоб зробити репортаж простішим ... якщо у вас є лише одна фіксація на зворотний порт (тобто прихильне посідання), то вибирати вишеньку легко ...

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


1
Гарна відповідь! Але підібрати вишневий асортимент досить просто, не впевнений, що я купую його як причину.
Стінглер

1
@stiggler Я особисто не купую це як причину, але я сприймав це як причину інших. IMHO інструмент для git - це те, що ви хочете, і скоєне скоєння - це зло ... але я б сказав, що наштовхнувшись на виправлення --first-parentсебе, щоб виграти аргумент проти скоєних комітетів ;-)
Стівен Конноллі

1
Це повинно бути прийнятою відповіддю. Набагато менше догми, і це свідчить про те, що фільтрування історії можна використовувати для того, щоб "мати свій торт і їсти його теж". Вам не доведеться знищувати історію, щоб надати чіткість дослідженням історії git.
ctpenrose

Вибрати вишеньку буде не так просто, якщо, накопичивши свої зобов'язання, ви згрупуєте багато змін у різні файли в один комітет. Я думаю, що це дуже різниться залежно від кодової бази, які зміни були внесені, скільки людей співпрацює тощо. Я не думаю, що ми можемо придумати єдине загальне правило, яке було б дійсним у всіх випадках.
Емі Пеллегріні

2

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


Строго кажучи, Git не дозволяє змінювати історію. Об'єкти фіксації незмінні. Змінюються лише вказівники гілок , і лише потім з "примусовим оновленням", яке, як правило, вважається чимось, що ви робите лише для цілей розвитку, а не на головній гілці. Ви завжди можете повернутися до попереднього стану за допомогою рефлогу, якщо тільки git gcне було запущено для відкидання невпорядкованих об'єктів.
Джон Перді

Ви маєте рацію, і, мабуть, я мав би це сказати вище. Однак я б заперечував, що щось на кшталт примусового натиску чи звільнення комітетів, які вже були відтіснені до віддаленого репо, було б кваліфіковане як історія перезапису, оскільки порядок і розташування комітетів так само важливі, як і самі комісії.
Фред Томсен

Це справедливо для певного коміту. У більшій картині я думаю, що інтерактивне перезавантаження та фільтр-гілка є настільки ефективно перезаписом історії, змінюючи її склад.
Майкл Дюрант

1
Для справедливості, SVN дотримується підходу "кожне вчинення є священним", але коли об'єднання створює єдину команду з цим злиттям і приховує зміни, які сприяли цьому, тому, схоже, всі SVN злиття "перезавантажуються". Їх немає, просто потрібно сказати команду історії, щоб показати вам об'єднані компоненти. Мені подобається такий підхід найкраще.
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 

це навіть не намагається вирішити поставлене запитання, чому squash git здійснює запити на тягнення? Дивіться, як відповісти
gnat

після спроби пояснення воно повинно це зробити ...
Йордан Георгієв

Я якось не бачу, як додаткове пояснення пропонує щось суттєве щодо питань, викладених та пояснених у відповідях, проголосованих у вершині, які були опубліковані кілька років тому (хоча вдосконалення першої редакції оцінено, хоча)
gnat

ключове слово - це "перспектива", перспективна концепція полегшує пояснення такого типу проблем в ІТ, наприклад, - ваша перспектива для відповіді на це питання є тією, яка вже надається, моя перспектива використовує ключове слово "перспектива" і надати практичний приклад того, як реалізувати той самий найкращий досвід, пояснений через різні точки зору ...
Йордан Георгієв,

1

Я хотів би побачити, буде код відкритим чи ні.

Коли проекти залишаються приватними:

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

Коли проекти стають загальнодоступними:

Скасувати все, тому що деякі комісії можуть містити витоки безпеки. Наприклад, пароль, який було зафіксовано та видалено знову.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.