Git - сквот всей ветки - одна команда squash

пока я работаю над новым кодом, я делаю много мелких коммитов для отслеживания изменений. Однако моя компания предпочитает, чтобы каждая функция была зафиксирована в одной транзакции. Таким образом, решение состоит в том, чтобы вырезать всю ветвь до одной фиксации.

Как вырезать всю ветку без использования git rebase --interactive, а затем меняя pick на squash для всех коммитов?

Ответ 1

Мой предпочтительный метод - двухстрочный (исключая шаги 1 и 4 ниже). Преимущества в том, что вам не нужно знать/записывать любые идентификаторы фиксации, вы можете написать простой псевдоним для выполнения всех шагов и фактическое перемещение всей ветки на происхождение/master, чтобы фактический слияние в мастер может быть быстрым, и конфликтов не может быть.

Во-первых, мои предположения:

  • Вы работаете над ветвью с именем my-feature-branch. Эта ветвь отклонилась от master несколькими коммитами; это отмеченная ветка.
  • Ваш локальный master отслеживает удаленную ветку origin/master
  • Вы хотите вырезать все свои коммиты из my-feature-branch в одно фиксированное ontop текущего состояния origin/master (а не локальный master, который может быть устаревшим)
  • Все ваши изменения зафиксированы, у вас нет неустановленных изменений (они будут потеряны во время git reset --hard)

Мой процесс выглядит следующим образом:

  • Извлечь, поэтому origin/master является текущим:

    $ git fetch
    
  • Отбросьте все коммиты в своей локальной ветке, сбросив его, чтобы указать на origin/master

    $ git reset --mixed origin/master
    
  • Слейте все свои старые изменения из предыдущего состояния вашей ветки в индекс

    $ git merge --squash [email protected]{1}
    
  • Зафиксируйте свои изменения - Git предварительно заполнит ваш редактор сообщением фиксации, содержащим все сообщения фиксации из раздавленных коммитов

Простой псевдоним, о котором я говорил, будет:

alias squash="git fetch; git reset --mixed origin/master; git merge --squash [email protected]{1}"

Ответ 2

Вероятно, лучшим вариантом для этого было бы использовать git merge --squash во время слияния. Это приведет к тому, что ваш филиал будет развиваться, что довольно часто становится проще в устранении неполадок, поскольку у вас будет некоторое понятие о том, что "я изменял эту специфическую функциональность в commit Z", и, глядя на эту конкретную фиксацию, у вас есть все контекст любых изменений, внесенных вами в несколько файлов, - просмотр одной фиксации, которая представляет собой сжатые результаты вашего пути развития, немного усложняет запоминание. "О, да, мне пришлось изменить эту другую вещь в другом файле, слишком...". У вас также есть преимущество использования git bisect, когда у вас есть весь доступный путь - все, что он мог сказать вам в раздавленном случае, - "эта огромная фиксация здесь сломала что-то".

Результатом использования git merge --squash является единая фиксация на ветке, которую вы "объединяете", в которую входят кумулятивные изменения из вашей ветки, но она оставляет только исходную ветвь.

Ответ 3

Найдите хеш для фиксации непосредственно перед тем, как начать ветвь и скопируйте ее в буфер обмена. Затем сделайте reset для этого хэша.

$ git reset [hash]

Затем просто повторно добавьте и повторно зафиксируйте изменения в одном сообщении.

$ git add -A
$ git commit -m 'EVERYTHING SQUASHED'

Ответ 4

Измените конфигурационный файл git ~/.gitconfig и добавьте следующее в раздел псевдонима

[alias]
    squash = "!f(){ CUR=`git rev-parse HEAD` && git reset --soft ${1} && git commit -m \"$(git log --format=%B ${1}..${CUR})\"; };f"

Этот псевдоним получает текущий хеш-код фиксации HEAD, сбрасывается обратно на указанный вами коммит и создает новую фиксацию, сохраняющую все сообщения фиксации.

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

git squash <refspec>

refspec может быть любой допустимой ссылкой фиксации, такой как хеш фиксации, имя ветки, имя тега, HEAD^ HEAD~3

Ответ 5

Я не думаю, что это правильный ответ на этот вопрос.

Но я обычно раздавливаю свою ветку, прежде чем делать запрос Pull для удаленного ведущего мастера, используя следующую команду:

git rebase -i master

Но вам все равно придется выбирать, что выбрать и сквош.

Ответ 6

Лучше всего сделать полный сброс и объединить предыдущую ГОЛОВКУ с сквошем. Вот псевдоним:

[alias]
  squash = "!f() { git reset --hard $1; git merge --squash [email protected]{1}; git commit; }; f"

Таким образом, вы можете назвать это так:

git squash master

Или сквош из другой ветки, как у dev:

git squash dev

Ответ 7

Это идеальный вариант использования для git reset --soft.

Предположим, у вас есть история коммитов

D   Your latest patch
C   Your second patch
B   Your first patch
A   Someone else work

у вас нет поэтапных изменений, и git status, git log или git show сообщают, что вы в настоящее время участвуете в коммите D.

Затем git reset --soft B возьмет кумулятивные изменения коммитов C и D и подготовит их для фиксации. git commit --amend затем "объединит" эти изменения в коммит B.

Используйте следующее:

git reset --soft B
git commit --amend

Вторая команда откроет ваш редактор с возможностью редактировать сообщение коммита.

Обратите внимание, что если вы подготовили поэтапные изменения до начала этого процесса (т.е. вы сделали git add XXX, но не выполнили git commit), то эти поэтапные изменения также будут объединены в коммит.