Як використовувати git merge --squash?


1208

У мене є віддалений сервер Git, ось сценарій, який я хочу виконати:

  • Для кожної помилки / функції я створюю іншу гілку Git

  • Я продовжую вводити свій код у цій гітці Git з неофіційними повідомленнями Git

  • У верхньому сховищі ми повинні виконати одну фіксацію для однієї помилки з офіційним повідомленням Git

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


1
Я не впевнений, чи я вас цілком зрозумів, але ви, можливо, захочете "злиття восьминога".
MatrixFrog

26
Зазвичай я використовую git rebase -i, щоб згорнути всі мої комітети в одну команду і переписати повідомлення про виконання Тоді я надсилаю його вище за течією.
Едвард Фолк

17
git merge --squashробить це все в командному рядку за один кадр, і ви просто сподіваєтесь, що це працює. git rebase -iпіднімає редактор і дозволяє точно налаштувати ребауз. Це повільніше, але ви можете бачити, що ви робите. Крім того, є різниця між rebase і merge, які є занадто задіяними для вирішення в коментарі.
Едвард Фолк

4
Проблема з усіма цими відповідями полягає в тому, що ви повинні бути на головній гілці локально і запустити команду merge --squash ... Я хочу запустити злиття - зніміть з гілки функції, а не головну гілку. коли я закінчу, я можу відсунути гілку функції на пульт та подати PR, чи можливо це?
Олександр Міллз

2
@AlexanderMills, я думаю, вам просто потрібна друга гілка функції (клонована з головного відділення). Виконайте merge --squashвід старого до нового, а потім з’єднайте нову гілку до головного. Стара гілка застаріла.
Гіроміт

Відповіді:


1998

Скажіть, ваша гілка виправлення помилок викликається, bugfixі ви хочете об'єднати її в master:

git checkout master
git merge --squash bugfix
git commit

Це візьме всі коміти з bugfixгілки, розбийте їх на 1 комітку та з’єднайте їх із вашою masterгілкою.


Пояснення :

git checkout master

Переключається на вашу masterфілію.

git merge --squash bugfix

Бере всі комісії з bugfixфілії та об'єднує їх із вашою поточною філією.

git commit

Створює єдину комісію з об'єднаних змін.

Пропускаючи -mпараметр, ви можете змінити чернетку повідомлення про фіксацію, що містить кожне повідомлення з ваших обтяжених зобов’язань перед завершенням вашої комісії.


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

12
Ви можете досягти цього, зробивши git commit --amend -m '...'пізніше.
Януш Ленар

19
У випадку, якщо конфлікти злиття трапляються і ви вирішите ці конфлікти, git commitбільше не відображатиметься корисне повідомлення про фіксацію, яке містить усі повідомлення про фіксацію. У такому випадку спробуйте git commit --file .git/SQUASH_MSG(через stackoverflow.com/a/11230783/923560 ).
Абдулл

23
Майте на увазі, що сквошінг за замовчуванням приписує комітети сквош . Щоб зберегти оригінального автора, потрібно чітко вказати його так:git commit -a --author="Author" --message="Issue title #id"
Габоровий

5
git merge --squashдозволяє створити єдиний коміт поверх поточної гілки, ефект якої такий же, як об'єднання іншої гілки. Але це не створить запис про злиття, а це означає, що ваш запит на виведення не матиме змін, але не буде позначений як об'єднаний! Отже, вам потрібно буде просто видалити цю гілку, яку потрібно зробити.
am0wa

129

Що, нарешті, це очистило для мене, це коментар, який показує, що:

git checkout main
git merge --squash feature

є еквівалентом діяльності:

git checkout feature
git diff main > feature.patch
git checkout main
patch -p1 < feature.patch
git add .

Коли я хочу об'єднати функціональну гілку з 105 (!!) фіксаціями та з’єднати їх усі в одну, я цього не хочу, git rebase -i origin/masterтому що мені потрібно окремо вирішити конфлікти злиття для кожного з проміжних комітетів (або принаймні тих, які git не може сам зрозуміти). Використання git merge --squashотримує мені результат, який я хочу, єдиного комітету для об'єднання цілої гілки функцій. І мені потрібно зробити не менше одного ручного вирішення конфлікту.


75
Я настійно пропоную виконати злиття в гілці функцій спочатку git merge master, а вже потім git merge --squash featureу головній гілці.
dotancohen

8
@dotancohen Вибачте за те, що виймаєте старий коментар :) Що можна отримати від об'єднання в гілці функцій перед тим, як виконувати git merge --squash featureз головного відділення?
бітмак

57
Спершу ви хочете об'єднати майстер у гілку функцій і мати справу з будь-якими ручними виправленнями у своїй гілці функцій. Це також дозволяє запустити тести і переконатися, що галузь функцій працює правильно. Тоді ви гарантуєте, що зможете зробити автоматичне злиття вашої функції гілки в головний.
Дан Кон

4
@dankohn Я пропоную вам додати у відповідь пояснення у вищезгаданому коментарі.
guntbert

3
@bitsmack: спочатку ви об'єднаєте майстер у функцію. Це дає вам можливість вирішити конфлікти щодо функції перед об'єднанням функції в головний
Майк

97

Ви хочете злитися з варіантом сквош. Ось якщо ви хочете робити це по одній гілці за раз.

git merge --squash feature1

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

git checkout feature1
git rebase -i master

Сквош в один комірок, потім повторіть для інших функцій.

git checkout master
git merge feature1 feature2 feature3 ...

Останнє злиття - це "злиття восьминога", оскільки воно об'єднує відразу багато гілок.

Сподіваюсь, це допомагає


3
Чому ви звільняєте?
Умаїр А.

12
@UmairAshraf - це інтерактивна база даних, яка дає вам можливість робити сквош у вашому відділенні.
andho

1
Звільнення - погана ідея. Не оновлюйте вже опубліковані
комісії

1
@ Sebi2020 git merge --squash відновить уже опубліковані комісії таким чином, що гірше, ніж інтерактивна база даних. Інтерактивна база даних (на гілці функцій) мало негативних наслідків.
xiix

1
@xiix Це справедливо лише в тому випадку, якщо ви єдиний, хто працює з галуззю функцій. Це не припущення, яке ви можете зробити. Рекомендую ознайомитись зі сторінками, пов’язаними з перезавантаженням на Git-SCM . У ньому зазначено: " Не перезавантажуйте комісії, які існують поза вашим сховищем, і люди, можливо, базуються на них. " природа git) ви не повинні цього робити.
Sebi2020

23

Якщо у вас є вже git merge bugfixна main, ви можете розчавити ваше злиття зробити в один з:

git reset --soft HEAD^1
git commit

git reset --soft HEAD^1Здається, скасовується остання фіксація, виконана перед злиттям, принаймні у випадку, якщо злиття буде швидким вперед.
Jesper Matthiesen

@JesperMatthiesen у випадку швидкого перемотування вперед ви не отримаєте зобов’язання про злиття, так що тоді ви зробите це git reset --soft HEAD^<number-of-commits-to-squash>.
qwertzguy

Це допомогло мені розбити все в єдиний комітет після злиття вниз за течією.
killjoy

18

Об’єднати newFeatureвідділення masterз власною командою:

git merge --squash newFeature && git commit -m 'Your custom commit message';

Якщо замість цього, ви робите

git merge --squash newFeature && git commit

ви отримаєте повідомлення про фіксацію, яке буде включати всі newFeatureфілії, які ви можете налаштувати.

Я це докладно пояснюю тут: https://youtu.be/FQNAIacelT4


10

Я знаю, що це питання стосується не конкретно Github, але оскільки Github настільки широко використовується, і це відповідь, яку я шукав, я поділюсь цим тут.

Github має можливість виконувати злиття сквош, залежно від параметрів злиття, включених у сховище.

Якщо включені сквош-злиття, параметр "Сквош та злиття" повинен з’являтися у спадному меню під кнопкою "Злиття".

Скріншот функції "Сквош і злиття" функції Github


GitHub використовує електронну пошту за замовчуванням, пов’язану з вашим обліковим записом. Якщо у вас є кілька адрес електронної пошти, і вам потрібно скористатися вторинною, ви не можете використовувати інтерфейс GH.
Лука

4

Припустимо, ви працювали в функції / task1 з декількома комісіями.

  1. Перейдіть до відділення проекту (project / my_project)

    git checkout project/my_project
    
  2. Створіть нову гілку (особливість / task1_bugfix)

    git checkout -b feature/task1_bugfix
    
  3. Мардж з --squashваріантом

    git merge --squash feature/task1
    
  4. Створіть одну комісію

    git commit -am "add single comments"
    
  5. Натисніть на своє відділення

    git push --set-upstream origin feature/task1_bugfix
    

1

Для Гіт

Створіть нову функцію

через термінал / оболонку:

git checkout origin/feature/<featurename>
git merge --squash origin/feature/<featurename>

Це не робить його, ви можете переглянути його спочатку.

Потім виконайте і закінчіть функцію з цієї нової гілки та видаліть / ігноруйте стару (ту, яку ви зробили на розробці).


@Melebius Єдине посилання на "SourceTree" є у вашому реченні, якщо це був тег або попереднє запитання: Він більше не існує.
Йордан Стефанеллі

1
@JordanStefanelli SourceTree було використано в оригінальній версії цієї відповіді . Дякуємо, що повідомили, що це виправлено!
Мелебій

1

якщо ви отримуєте помилку: введення даних неможливо, оскільки у вас є неперероблені файли.

git checkout master
git merge --squash bugfix
git add .
git commit -m "Message"

виправлено всі файли конфлікту

git add . 

ви також можете використовувати

git add [filename]

0

Щоб розігнати місцеву гілку, перш ніж натиснути на неї:

  1. оформити роботу відповідної філії, якщо вона ще не була зареєстрована.

  2. Знайдіть ша найдавнішого зобов'язання, яке хочете зберегти.

  3. Створіть / оформить нову гілку (tmp1) з цього коміту.

    git checkout -b tmp1 <sha1-of-commit>

  4. Об’єднайте оригінальну гілку в нову, присипавши.

    git merge --squash <original branch>

  5. Здійсніть зміни, які були створені об'єднанням, за допомогою короткого повідомлення про фіксацію.

    git commit -m <msg>

  6. Оформіть оригінальну гілку, яку ви хочете збити.

    git checkout <branch>

  7. Скиньте оригінали, які ви хочете зберегти.

    git reset --soft <sha1>

  8. Обновіть цю гілку на основі нової гілки tmp1.

    git rebase tmp1

  9. Це все - тепер видаліть тимчасову гілку tmp1, як тільки ви впевнені, що все в порядку.


0

Ви можете використовувати інструмент, який я створив, щоб полегшити цей процес: git-squash . Наприклад, щоб розбити всі коміти на гілку функції, яка була відгалужена від головної гілки, напишіть:

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