Як використовувати 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.