Git: Как раздавить все коммиты на ветке

315

Я делаю новую ветку из master:

git checkout -b testbranch

Я делаю 20 коммитов в это.

Теперь я хочу раздавить эти 20 коммитов. Я делаю это с:

git rebase -i HEAD~20

А если я не знаю, сколько коммитов? Есть ли способ сделать что-то вроде:

git rebase -i all on this branch
user3803850
источник
6
Вы можете выполнить git rebase -i 58333012713fc168bd70ad00d191b3bdc601fa2dинтерактивную перебазировку, где commitnumber - это последний коммит, который остается неизменным
denns
@denns Используя этот метод с последней фиксацией в филиале вы перебазирование из работали фантастическими. Спасибо!
Джошуа Пинтер

Ответы:

395

Еще один способ уничтожить все ваши коммиты - сбросить индекс на master:

 git checkout yourBranch
 git reset $(git merge-base master yourBranch)
 git add -A
 git commit -m "one commit on yourBranch"

Это не идеально, так как подразумевает, что вы знаете, из какой ветки идет ваш филиал.
Примечание: найти эту исходную ветку нелегко / невозможно с помощью Git ( визуальный способ часто самый простой , как показано здесь ).


РЕДАКТИРОВАТЬ: вам нужно будет использовать git push --force


Карлоча Хоа добавляет в комментариях :

Для сброса вы можете сделать

git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD)) 

[Это] автоматически использует ветку, в которой вы находитесь.
И если вы используете это, вы также можете использовать псевдоним, так как команда не полагается на имя ветви .

VonC
источник
2
Лучше оформить заказ, чтобы зафиксировать, где в YourBranchданный момент. Это сохранится, YourBranchкогда вы это сделаетеreset
Евгений Коньков
1
@Abdurrahim Или откройте git bash, и вы сможете скопировать и вставить эти команды!
VonC
3
Для сброса вы можете git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))автоматически использовать ветку, в которой вы находитесь. И если вы используете это, вы также можете использовать псевдоним, так как команда не полагается на имя ветви.
Karlotcha Hoa
1
@Druska Для случаев ветвления simlpe, нет, это должно работать нормально.
VonC
1
@ Шимми, да, при условии, что вы принудительно нажмете после перезагрузки: git push --force(и предупредите своих коллег, если в этой ветке работает несколько человек)
VonC
112

Оформите ветку, для которой вы хотите объединить все коммиты в один коммит. Скажем, это называется feature_branch.

git checkout feature_branch

Шаг 1:

Сделайте программный сброс вашего origin/feature_branchс вашим местным masterфилиалом (в зависимости от ваших потребностей, вы можете сбросить с помощью origin / master). Это сбросит все дополнительные коммиты в вашем feature_branch, но без каких-либо изменений вашего файла локально.

git reset --soft master

Шаг 2:

Добавьте все изменения в вашем каталоге git repo в новый коммит, который будет создан. И совершить то же самое с сообщением.

git add -A && git commit -m "commit message goes here"

shanky
источник
6
Это было самое надежное решение для меня - не вызывать ни ошибок перебазирования, ни конфликтов слияния.
АНТАРА
1
Предупреждение: в git добавьте -A добавьте ВСЕ, что есть в локальной папке, - в ветку.
Дэвид Х
люблю это решение! это именно то, что я хотел!
Якобалленвуд
1
Лучшее решение для noob - неразрушающий и только упс момент может быть проверка слишком много, таких как секреты приложения и т. Д., Которые не должны иметь значения, если у вас есть правильный файл
gitignore
@NSduToit Краткий ответ: нет, не нужно. После выполнения вышеупомянутых шагов в моем ответе вы получите один коммит с некоторыми изменениями кода. Вы можете думать об этом как о любом другом коммите с некоторыми изменениями кода. Вы можете отправить это в удаленную ветку без -fфлага.
shanky
110

То, что вы делаете, довольно подвержено ошибкам. Просто сделать:

git rebase -i master

который автоматически перебазирует только коммиты вашей ветки на текущий последний мастер.

Eevee
источник
5
спасибо, я получил это, но почему моя системная ошибка склонна
user3803850
10
Возможно потому, что легко ошибиться с номером?
Даниэль Скотт
13
Согласитесь, это ваше лучшее решение. но перейдите по этой ссылке, поскольку она лучше объясняет, что вам нужно сделать.
Кристо
3
Вместо того, чтобы уничтожать коммиты, вы можете объединить ветку с мастером и выполнить git reset на origin / master, чтобы снять все коммиты. Это позволило бы вам зафиксировать свой существующий неотмеченный код сcommit -am "the whole thing!"
nurettin
2
@nurettin Я думаю, что reset origin/masterметод действительно плохой, так как это то же самое, что делать коммиты непосредственно на master - нет истории 'merge branch', нет опции pull request. Я думаю, что ответ @WaZaA намного больше соответствует нормальному рабочему процессу git
Drenai
79

Еще один простой способ сделать это: перейти на ветку origin и сделать a merge --squash. Эта команда не выполняет "сдавленный" коммит. когда вы это сделаете, будут собраны все сообщения о коммитах вашей ветки.

$ git checkout master
$ git merge --squash yourBranch
$ git commit # all commit messages of yourBranch in one, really useful
 > [status 5007e77] Squashed commit of the following: ...
WaZaA
источник
1
Правда. Я упомянул разницу между слияниями --squash и rebase -i в stackoverflow.com/a/2427520/6309
VonC
1
Это работает, если вы не хотите сквош в родительскую ветвь, просто создайте и переключитесь на новую ветвь, основанную на родительской ветке, и сделайте сквош с этим.
Шарлотта
Ура, приятель, отличный совет!
Нестор Миляев
отлично! я создаю "временную" ветку от "главной", чтобы сначала раздавить "вашу ветку", а затем объединить "временную" с "главной".
Лазибур
34

Предполагая, что вы переходили от мастера, вам не нужно yourBranchвсе время входить в шаг сброса:

git checkout yourBranch
git reset --soft HEAD~$(git rev-list --count HEAD ^master)
git add -A
git commit -m "one commit on yourBranch"

Пояснение :

  • git rev-list --count HEAD ^masterподсчитывает коммиты, так как вы сделали свою ветку объектов от мастера, например. 20.
  • git reset --soft HEAD~20сделает мягкий сброс последних 20 коммитов. Это оставляет ваши изменения в файлах, но удаляет коммиты.

Использование :

В моем .bash_profile я добавил псевдоним для gisquashэтого одной командой:

# squash all commits into one
alias gisquash='git reset --soft HEAD~$(git rev-list --count HEAD ^master)'

После сброса и фиксации вы должны сделать a git push --force.

Подсказка :

Если вы используете Gitlab> = 11.0, вам больше не нужно это делать, поскольку у него есть опция сжатия при объединении ветвей. Gitlab Squashing опция

ОМП
источник
15

Основываясь на прочтении нескольких вопросов Stackoverflow и ответов на вопрос об использовании, я думаю, что это хороший вариант для того, чтобы раздавить все коммиты на ветке:

git reset --soft $(git merge-base master YOUR_BRANCH) && git commit -am "YOUR COMMIT MESSAGE" && git rebase -i master

Это при условии, что мастер является базовой веткой.

Трэвис Ридер
источник
1
Большое спасибо, компания имеет много ограничений и не смогла перебазировать обычным способом с редактором, так как не было вслух сохранить. Также не может использовать функцию сквоша и слияния в git, так как эта ветка идет к Lead Dev для слияния, и ему это не нравится. Этот 1 лайнер работал и спас головные боли. Хорошая работа.
L1ghtk3ira
10

Решение для людей, которые предпочитают нажимать:

  1. Установите sourcetree (это бесплатно)

  2. Проверьте, как выглядят ваши коммиты. Скорее всего у вас что-то похожее на это введите описание изображения здесь

  3. Щелкните правой кнопкой мыши на родительском коммите. В нашем случае это основная ветка.

введите описание изображения здесь

  1. Вы можете сдавить коммит с предыдущим, нажав кнопку. В нашем случае мы должны нажать 2 раза. Вы также можете изменить сообщение коммита введите описание изображения здесь

  2. Результаты потрясающие, и мы готовы к этому! введите описание изображения здесь

Примечание: если вы выдвигали свои частичные коммиты на дистанционное управление, вы должны использовать принудительный толчок после сквоша

Марчин Шимчак
источник
Спасибо за это!
Кристалл
0

Другим решением было бы сохранить все журналы фиксации в файл

git log> branch.log

Теперь branch.log будет иметь все идентификаторы коммитов с начала. Прокрутите вниз и возьмите первый коммит (это будет сложно в терминале), используя первый коммит

git reset --soft

все коммиты будут раздавлены

Pranav
источник
0

Git reset, как упоминалось во многих ответах ранее, безусловно, лучший и самый простой способ достичь того, чего вы хотите. Я использую его в следующем рабочем процессе:

(на ветке разработки)

git fetch
git merge origin/master  #so development branch has all current changes from master
git reset origin/master  #will show all changes from development branch to master as unstaged
git gui # do a final review, stage all changes you really want
git commit # all changes in a single commit
git branch -f master #update local master branch
git push origin master #push it
Маркус
источник
0

Весь этот git reset, hard, soft и все остальное, упомянутое здесь, вероятно, работает (это не для меня), если вы делаете шаги правильно и что-то вроде джинна.
Если вы средний Джо Смо, попробуйте следующее:
Как использовать git merge --squash?


Спасла мне жизнь, и я буду играть в сквош, используя это 4 раза, так как я узнал об этом. Простой, чистый и в основном 1 комад. Вкратце:


если вы находитесь на ветке, давайте назовем ее «my_new_feature» от разработки, и ваш запрос на выборку имеет 35 коммитов (или столько же), и вы хотите, чтобы это было 1.

A. Убедитесь, что ваша ветка обновлена, перейдите на разрабатывать, получать последние версии, объединять и разрешать любые конфликты с помощью «my_new_feature»
(этот шаг на самом деле вы должны предпринять как можно быстрее, в любом случае)

B. Получить последние из разработки и расшириться в новом филиале называют его «my_new_feature_squashed»

C. магия здесь.
Вы хотите перенести свою работу из "my_new_feature" в "my_new_feature_squashed".
Просто сделайте это (в то время как в вашей новой ветке мы создали от разработки):
git merge --squash my_new_feature

Все ваши изменения теперь будут в вашей новой ветке, не стесняйтесь тестировать ее, затем просто сделайте свой 1 единственный коммит, нажмите, новый PR этой ветки - и ждите повторения на следующий день.
Ты не любишь кодировать? :)

ItaiRoded
источник
0

Вы можете использовать инструмент, который я создал специально для этой задачи:

https://github.com/sheerun/git-squash

В основном вам нужно позвонить, git squash masterи все готово

sheerun
источник