Об’єднайте (за допомогою сквош) усі зміни з іншої гілки як єдиний комітет


479

Чи існує спосіб Git об'єднати всі зміни з однієї гілки в іншу, але одночасно скористатися одною коміткою?

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

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

Чи є простий спосіб це зробити?

Як варіант, як щодо команди, яка стискає всі фіксації на гілці з моменту її розгалуження?

Відповіді:


601

Інший варіант - це, git merge --squash <feature branch>нарешті, зробити git commit.

З Git злиття

--squash

--no-squash

Створіть робоче дерево та стан індексу так, ніби сталося справжнє злиття (за винятком інформації про злиття), але насправді не виконайте фіксацію чи переміщення HEAD, а також запис, $GIT_DIR/MERGE_HEADщоб викликати наступну git commitкоманду для створення об'єднання об'єднань. Це дозволяє створити єдиний комірок поверх поточної гілки, ефект якої такий же, як об’єднання іншої гілки (або більше у випадку восьминога).


1
Класна функція! Я люблю git. Хоча я напевно буду використовувати це в майбутньому зараз, я все-таки рекомендую ознайомитись із способом перегляду бази даних -i. Це добре вміння мати, на всякий випадок, якщо ви дійсно захотіли зробити їх більше, ніж лише один.
Бук Бак

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

23
Це, і, будьте попереджені, філія не буде розглядатися як об'єднана. stackoverflow.com/questions/19308790/…
Райан

3
ІМХО це повинно було називатисяrebase --squash
Енді

тож (оскільки це дійсно не об'єднує галузь функції), це було б доречно, якщо ви збиралися видалити гілку функції після фіксації. Це правильно? (Я не експерт з git)
Ендрю Спенсер

214

Знайшов це! Команда об’єднання має --squashопцію

git checkout master
git merge --squash WIP

на цьому етапі все зливається, можливо, конфліктує, але не вчиняється. Тож я зараз можу:

git add .
git commit -m "Merged WIP"

2
що робить git add .?
Майкл Поттер

1
@MichaelPotter Він додає всі файли та зміни
Дакш Шах

2
git add .додає всі неігноровані файли в поточну директорію, я б насторожено ставлюся до того, щоб не збирати файли ненавмисні.
Джейк Кобб

7
В якості альтернативи git add .ви можете використовувати git add -uлише додавання файлів, які вже додані до дерева.
Брендон Огл

19
Пропонуємо, що "git add". також бути зроблено заплутано. Коли я роблю "git merge - skquash WIP", в індексі вже є зміни, що відбулися. Все, що потрібно, - це зробити їх. Робимо "git add". додасть зміни, які трапляються у робочому каталозі, але вони не входили до гілки функцій. Питання полягало в тому, як здійснити зміни у галузі функції як одне ціле.
Іван Панкович

30

Спробуйте git rebase -i masterу своїй функції. Потім ви можете змінити всі, крім одного "вибору" на "сквош", щоб об'єднати коміти. Дивіться комбіновані комісії з базою даних

Нарешті, ви можете зробити злиття з головного відділення.


8
Так, це працює, але я не хочу зайвих інтерактивних баз даних. Я просто хочу все, оскільки гілка сплюснулася.
Бред Робінсон

2
+1 Це робить чистою історію. Набагато простіше визначити та керувати комісіями як окремими патчами, картками, історіями тощо
Ryan

2

Використання git merge --squash <feature branch>як прийнятої відповіді пропонує трюк, але воно не покаже об'єднану гілку як фактично злиту.

Тому ще кращим рішенням є:

  • Створіть нову гілку від останнього майстра
  • Об’єднайтесь <feature branch>у вищезазначене, використовуючиgit merge --squash
  • Об’єднайте новостворену гілку в головну

Ця вікі докладно пояснює процедуру.


0

Я створив власний псевдонім git, щоб зробити саме це. Я називаю це git freebase! Він візьме наявну безладну, непереборну гілку функцій та відтворить її так, що вона стане новою гілкою з тим самим ім'ям, що її коміти врізаються в один коміт і перезавантажуються на вказану вами гілку (master за замовчуванням). У самому кінці це дозволить вам використовувати будь-яке повідомлення про фіксацію, яке вам подобається, для вашої щойно "вільно базованої" гілки.

Встановіть його, розмістивши у своєму .gitconfig наступний псевдонім:

[alias]
  freebase = "!f() { \
    TOPIC="$(git branch | grep '\\*' | cut -d ' ' -f2)"; \
    NEWBASE="${1:-master}"; \
    PREVSHA1="$(git rev-parse HEAD)"; \
    echo "Freebaseing $TOPIC onto $NEWBASE, previous sha1 was $PREVSHA1"; \
    echo "---"; \
    git reset --hard "$NEWBASE"; \
    git merge --squash "$PREVSHA1"; \
    git commit; \
  }; f"

Використовуйте його у своїй функції, запустивши: git freebase <new-base>

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

Я буду підтримувати його в моєму dotfiles repo на github: https://github.com/stevecrozz/dotfiles/blob/master/.gitconfig


працював як блаженство! Ви можете також поглянути на evernote.com/shard/s52/sh/7f8f4ff1-9a68-413f-9225-c49e3ee2fafd/…
Ілля Шершофф

-1

git merge --squash <feature branch> це "хороший варіант". "git počin" повідомляє вам всі функції фіксації гілки з вибором, щоб зберегти це.

Для меншої кількості об'єднань.

git merge do x times - git скидання HEAD ^ --soft, то git commit.

Ризик - видалені файли можуть повернутися.


-5

Це можна зробити за допомогою команди "rebase". Назвемо гілки "головними" та "функціональними":

git checkout feature
git rebase main

Команда rebase відтворює всі зобов’язання на "функцію" як один фіксатор з батьківським рівнем "main".

Ви можете запустити git merge mainраніше, git rebase mainякщо "головний" змінився з моменту створення "функції" (або з моменту останнього злиття). Таким чином, ви все ще маєте свою повну історію у випадку, якщо у вас виник конфлікт злиття.

Після відновлення бази даних ви можете об'єднати свою гілку до основної, що призведе до швидкого злиття вперед:

git checkout main
git merge feature

Див Rebase сторінку Розуміння Git Концептуально хороший огляд


Це не спрацювало для мене. Я щойно створив просту тестову репо з гілкою WIP і спробував вищезазначене і зіткнувся з конфліктами (навіть якщо я не вніс жодних змін на майстер).
Бред Робінсон

Якщо функція була створена з main (git checkout -b function main), і у вас відбулося недавнє злиття з main, вам не слід отримувати конфлікти з
ребазою

Добре, спробуй ще раз. Цього разу не траплялися конфлікти, але історія не розбита.
Бред Робінсон

Поглянувши на документацію на git-merge, ви праві, деякі з комісій залишаться. Якщо ви зробили попередні злиття з "головного" в "функціональне", тоді ребаза видалить деякі з них, але не всі.
NamshubWriter

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