Сквош мой последний X коммитов вместе с помощью Git - PullRequest
3036 голосов
/ 04 марта 2011

Как мне сжать мои последние X коммитов в один коммит с помощью Git?

Ответы [ 31 ]

29 голосов
/ 26 июня 2018

Ответ аномалий хорошо, но я чувствовал себя неуверенно по этому поводу, поэтому я решил добавить пару скриншотов.

Шаг 0: git log

Посмотрите, где вы находитесь с git log. Самое главное, найти хеш коммита первого коммита, который вы не хотите раздавить. Так что только:

enter image description here

Шаг 1: git rebase

Выполнить git rebase -i [your hash], в моем случае:

$ git rebase -i 2d23ea524936e612fae1ac63c95b705db44d937d

Шаг 2: выбрать / раздавить, что вы хотите

В моем случае я хочу раздавить все на коммите, который был первым в истории. Порядок указывается от первого до последнего, так же как и в git log. В моем случае я хочу:

enter image description here

Шаг 3: настроить сообщение (я)

Если вы выбрали только один коммит и раздавили остальные, вы можете настроить одно сообщение о коммите:

enter image description here

Вот и все. Как только вы сохраните это (:wq), все готово. Посмотрите на это с git log.

27 голосов
/ 11 июля 2018

В ветке, в которой вы хотите объединить коммиты, запустите:

git rebase -i HEAD~(n number of commits back to review)

пример:

git rebase -i HEAD~1

Это откроет текстовый редактор, и вы должны переключить «pick» перед каждым коммитом с помощью «squash», если вы хотите, чтобы эти коммиты были объединены вместе. Из документации:

p, pick = use commit

s, squash = использовать коммит, но объединить с предыдущим коммитом

Например, если вы хотите объединить все коммиты в один, «пикап» - это первый сделанный вами коммит, и все будущие (помещенные ниже первого) должны быть установлены на «сквош». Если используется vim, используйте : x в режиме вставки для сохранения и выхода из редактора.

Затем, чтобы продолжить ребаз:

git rebase --continue

Подробнее об этом и других способах переписывания истории коммитов см. этот полезный пост

25 голосов
/ 09 сентября 2015

Если вы находитесь в удаленной ветви (называемой feature-branch), клонированной из Золотого репозитория (golden_repo_name), то вот метод, позволяющий объединить ваши коммиты в один:

  1. Оформить заказ на золотой репо

    git checkout golden_repo_name
    
  2. Создайте из него новую ветку (золотой репо) следующим образом

    git checkout -b dev-branch
    
  3. Слияние сквоша с вашим местным филиалом, который у вас уже есть

    git merge --squash feature-branch
    
  4. Зафиксируйте ваши изменения (это будет единственный коммит в ветке dev)

    git commit -m "My feature complete"
    
  5. Переместить ветку в локальный репозиторий

    git push origin dev-branch
    
18 голосов
/ 14 сентября 2017

Что может быть действительно удобным:
Найдите хеш коммита, над которым вы хотите заключить, скажем d43e15.

Теперь используйте

git reset d43e15
git commit -am 'new commit name'
16 голосов
/ 04 марта 2011

Это очень круто, но довольно круто, так что я просто брошу его на ринг:

GIT_EDITOR='f() { if [ "$(basename $1)" = "git-rebase-todo" ]; then sed -i "2,\$s/pick/squash/" $1; else vim $1; fi }; f' git rebase -i foo~5 foo

Перевод: предоставьте новый «редактор» для git, который, если имя редактируемого файла равно git-rebase-todo (интерактивная подсказка rebase), изменяет все, кроме первого «pick» на «squash», а в противном случае порождает vim - так что когда вам предложат отредактировать сжатое сообщение о коммите, вы получите vim. (И, очевидно, я давил последние пять коммитов на ветке foo, но вы можете изменить это так, как вам нравится.)

Я бы, наверное, сделал то, что Марк Лонгэйр предложил , однако.

14 голосов
/ 20 августа 2016

Если вы хотите использовать каждый коммит в один коммит (например, при первом публичном выпуске проекта), попробуйте:

git checkout --orphan <new-branch>
git commit
10 голосов
/ 20 марта 2018

Я думаю, что самый простой способ сделать это - создать новую ветку из master и выполнить слияние --squash из ветви feature.

git checkout master
git checkout -b feature_branch_squashed
git merge --squash feature_branch

Тогда все изменения готовы к фиксации.

9 голосов
/ 21 августа 2018

Чтобы раздавить последние 10 коммитов в 1 отдельный коммит:

git reset --soft HEAD~10 && git commit -m "squashed commit"

Если вы также хотите обновить удаленную ветку с помощью сжатого коммита:

git push -f
8 голосов
/ 02 ноября 2018

⚠️ ПРЕДУПРЕЖДЕНИЕ: «Мои последние X коммитов» могут быть неоднозначными.

  (MASTER)  
Fleetwood Mac            Fritz
      ║                    ║
  Add Danny  Lindsey     Stevie       
    Kirwan  Buckingham    Nicks                                              
      ║         ╚═══╦══════╝     
Add Christine       ║          
   Perfect      Buckingham
      ║           Nicks            
    LA1974══════════╝                                    
      ║                  
      ║                  
    Bill <══════ YOU ARE EDITING HERE
  Clinton        (CHECKED OUT, CURRENT WORKING DIRECTORY)              

В этой очень сокращенной истории репозитория https://github.com/fleetwood-mac/band-history вы открыли пул-запрос на слияние вкоммит Билла Клинтона в исходный (MASTER) коммит Fleetwood Mac.

Вы открыли пулл-запрос, и на GitHub вы видите это:

Четыре коммита:

  • Добавить Дэнни Кирвана
  • Добавить Кристин Идеал
  • LA1974
  • Билл Клинтон

Думая, что никто никогда не захочет читать полную историю хранилища,(На самом деле есть хранилище, нажмите на ссылку выше!) Вы решаете раздавить эти коммиты.Итак, вы идете и запускаете git reset --soft HEAD~4 && git commit.Затем вы git push --force отправляете его на GitHub для очистки вашего PR.

И что происходит?Вы только что сделали один коммит от Фрица до Билла Клинтона.Потому что вы забыли, что вчера вы работали над версией Бекингемского Ника.И git log не соответствует тому, что вы видите на GitHub.

? МОРАЛЬ ИСТОРИИ

  1. Найдите нужные вам файлы и git checkout их
  2. Найдите точный предыдущий коммит, который вы хотите сохранить в истории, и git reset --soft, который
  3. Создает git commit, который искажается непосредственно от к до
7 голосов
/ 14 февраля 2019

Простой однострочник, который всегда работает, учитывая, что вы в данный момент находитесь в ветви, которую хотите сжать, master - это ветвь, из которой он возник, а последний коммит содержит сообщение о коммите и автора, которого вы хотите использовать:

git reset --soft $(git merge-base HEAD master) && git commit --reuse-message=HEAD@{1}
...