Як ти сквош здійснює один патч з форматом git-patch?


163

У мене є вісім комісій у філії, які я хотів би надіслати електронною поштою деяким людям, які ще не є освіченими. Поки що все, що я роблю, дає мені 8 патч-файлів, або починає надавати мені патч-файли за кожну фіксацію в історії філії, починаючи з початку часу. Я використовував git rebase - інтерактивний, щоб скрутити коміти, але тепер усе, що я намагаюся, дає мені мільйони патчів з початку часу. Що я роблю неправильно?

git format-patch master HEAD # yields zillions of patches, even though there's 
                             # only one commit since master

Мені цікаво, яким методом ви в кінцевому підсумку скористаєтесь серед пропозицій нижче. Повідомте нас;)
VonC

4
Я буду використовувати git diff, як запропонував Роб Ді Марко. Але я не працюю два тижні, щойно став свідком народження моєї другої дівчинки минулої ночі, тож пройде ще деякий час, перш ніж я її використаю! :)
skiphoppy

2
Я хотів би побачити git format-patch - майстер сквош HEAD
schoetbi

1
Спробуйте master..HEAD, щоб вказати діапазон оборотів.
Конрад Кляйн

Відповіді:


186

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

[adam@mbp2600 example (master)]$ git checkout -b tmpsquash
Switched to a new branch "tmpsquash"

[adam@mbp2600 example (tmpsquash)]$ git merge --squash newlines
Updating 4d2de39..b6768b2
Fast forward
Squash commit -- not updating HEAD
 test.txt |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git commit -a -m "My squashed commits"
[tmpsquash]: created 75b0a89: "My squashed commits"
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git format-patch master
0001-My-squashed-commits.patch

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


2
Це те, що я використовую, коли хочу зберігати історію локально (у випадку, якщо мені потрібно буде редагувати виправлення). В іншому випадку я просто використовую rebase -i і розбиваю коміти.
sebnow

5
для мене вона працювала надійніше, git comit -m "My squashed commits"інакше вона додала б інші незафіксовані файли
Себастьян,

Крім того, ви можете переключитися на певну команду замість ведучого та зробити це, щоб створити патч від "виконувати", щоб:git checkout 775ec2a && git checkout -b patch && git merge --squash branchname
Беррі М.

131

Просто для додання ще одного рішення до горщика: Якщо ви використовуєте це замість:

git format-patch master --stdout > my_new_patch.diff

Тоді це ще буде 8 патчів ... але всі вони будуть в одному патч-файлі і застосовуватимуться як один із:

git am < my_new_patch.diff

13
Мені подобається це рішення. Варто зауважити, що це може створити іноді набагато більший виправлення, ніж метод, описаний @Adam Alexander. Це відбувається тому, що деякі файли можуть редагуватися не один раз через коміти. Цей метод розглядає кожну комісію окремо, навіть якщо якийсь файл було повернено. Але більшість часу це не проблема.
гумік

1
Цей варіант чудовий, якщо ви намагаєтесь уникнути злиття! (наприклад, ви хочете пропустити деякі комісії). Ви можете ще git rebase -i ...і розім'яти їх до одного.
Хорхе Орпінель

21

Я завжди використовую git diff, тому у вашому прикладі щось подібне

git diff master > patch.txt

15
За винятком випадків, коли ви втрачаєте всі повідомлення та метадані. Краса формату-патчу git полягає в тому, що можна реконструювати цілу гілку з набору патчів.
mcepl

метод create-branch-and-squash має перевагу поєднання всіх повідомлень про фіксацію в одне, але цей спосіб набагато швидший, якщо ви хочете написати власне повідомлення про фіксацію
woojoo666

насправді комбіноване повідомлення можна зробити за допомогою git log, див. приклад моєї відповіді
woojoo666

2
Хороший варіант, але врахуйте, що "git diff" не може включати бінарні відмінності (можливо, є варіант зробити це).
Сантьяго Віллафуерте

18

Це адаптація відповіді Адама Олександра на випадок, якщо ваші зміни знаходяться в головній галузі. Для цього виконайте такі дії:

  • Створює нову гілку "tmpsquash" з потрібної точки (шукайте ключ SHA, який працює з "git --log" або з gitg. Виберіть команду, яку ви хочете бути tmpsquash head. Звернення, які після цього в master будуть, будуть збита скоєна).
  • Об'єднує зміни з головного в tmpsquash.
  • Здійснює зубчасті зміни в tmpsquash.
  • Створює патч з нарізаними комітами.
  • Повертається до головного відділення

laura@rune:~/example (master)$ git branch tmpsquash ba3c498878054e25afc5e22e207d62eb40ff1f38
laura@rune:~/example (master)$ git checkout tmpsquash
Switched to branch 'tmpsquash'
laura@rune:~/example (tmpsquash)$ git merge --squash master
Updating ba3c498..40386b8
Fast-forward
Squash commit -- not updating HEAD

[snip, changed files]

11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git commit -a -m "My squashed commits"
[test2 6127e5c] My squashed commits
11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git format-patch master
0001-My-squashed-commits.patch
laura@rune:~/example  (tmpsquash)$ git checkout master
Switched to branch 'master'
laura@rune:~/example  (master)$

Внесення змін у програмі master є анти-закономірністю, якщо ви не будете підштовхувати їх до віддалення. І якщо ви хочете, вам, ймовірно, не потрібно генерувати файли патчів для них.
ivan_pozdeev

18

Як ви вже знаєте, git format-patch -8 HEADви отримаєте вісім патчів.

Якщо ви хочете, щоб ваші 8 комісій відображалися як один, і не проти переписувати історію своєї філії ( o-o-X-A-B-C-D-E-F-G-H), ви можете:

git rebase -i
// squash A, B, C, D, E ,F, G into H

або, і це було б кращим рішенням, повторити всі ваші 8 зобов’язань з X(зобов’язання перед вашими 8 зобов’язаннями) на новій гілці

git branch delivery X
git checkout delivery
git merge --squash master
git format-patch HEAD

Таким чином, у вас є лише одна фіксація у відділенні "доставка", і вона представляє всі ваші останні 8 зобов'язань


git merge masterпросто робить швидкий вперед і не сквош здійснює один. Змініть, щоб git merge --squash masterусі комісії були розбиті та помітні в інсценованій зоні. Ваш потік буде працювати з цією зміною. (Я використовую git версії 2.1.0.)
оглушення

5

Формат-патч між двома тегами:

git checkout <source-tag>
git checkout -b <tmpsquash>
git merge --squash <target-tag>
git commit -a -m "<message>"
git format-patch <source-tag>

5

Найпростіший спосіб - використовувати git diffта додавати, git logякщо ви хочете, щоб комбіноване повідомлення про фіксацію, яке виведе метод сквош. Наприклад, щоб створити патч між фіксацією abcdта 1234:

git diff abcd..1234 > patch.diff
git log abcd..1234 > patchmsg.txt

Потім при застосуванні пластиру:

git apply patch.diff
git add -A
git reset patch.diff patchmsg.txt
git commit -F patchmsg.txt

Не забувайте про --binaryаргументи, git diffколи ви маєте справу з нетекстовими файлами, наприклад зображеннями чи відеозаписами.


0

На основі відповіді Адама Олександра:

git checkout newlines
## must be rebased to master
git checkout -b temporary
# squash the commits
git rebase -i master
git format-patch master
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.