Объединить все изменения из другой ветки в один коммит

В Git есть ли способ слить все изменения из одной ветки в другую, но сквош в одну фиксацию одновременно?

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

Как только эта работа будет завершена, и я хочу объединить ветвь WIP обратно в master, я бы хотел отбросить все эти промежуточные коммиты и просто иметь чистую фиксацию.

Есть ли простой способ сделать это?

В качестве альтернативы, как насчет команды, которая выкалывает все фиксации на ветке с точки, где она была разветвленной?

Ответ 1

Другим вариантом является git merge --squash <feature branch> затем, наконец, выполните git commit.

Из Git слияния

--squash

--no-squash

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

Ответ 2

Нашел! Команда Merge имеет параметр --squash

git checkout master
git merge --squash WIP

в этот момент все сливается, возможно, конфликтует, но не совершается. Теперь я могу:

git add .
git commit -m "Merged WIP"

Ответ 3

Попробуйте git rebase -i master в вашей ветке функций. Затем вы можете изменить все, кроме одного "выбрать", чтобы "сквош", чтобы комбинировать коммиты. См. squashing commits with rebase

Наконец, вы можете выполнить слияние с главной ветвью.

Ответ 4

Я создал свой псевдоним 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 на github: https://github.com/stevecrozz/dotfiles/blob/master/.gitconfig

Ответ 5

git merge --squash <feature branch> - хороший вариант. "git commit" сообщает вам все сообщения о фиксации ветки объекта с вашим выбором, чтобы сохранить его.

За меньшее слияние.

git merge do x times - git reset HEAD ^ --soft затем git commit.

Риск-удаленные файлы могут вернуться.

Ответ 6

Я хотел раздавить все коммиты в моем хозяине в одном. Я пробовал это безуспешно:

$ git checkout --orphan new_master
$ git merge --squash master
fatal: Squash commit into empty head not supported yet

Итак, я сделал это:

$ tar cf /tmp/git.tar --exclude .git .
$ git checkout --orphan new_master
$ tar xf /tmp/git.tar
$ git commit -m "Initial commit"

который работал красиво.

Ответ 7

Вы можете сделать это с помощью команды "rebase". Позвольте называть ветки "основной" и "особенностью":

git checkout feature
git rebase main

Команда rebase будет воспроизводить все коммиты на "функции" как одну фиксацию с родительским, равным "main".

Возможно, вы захотите запустить git merge main до git rebase main, если "main" изменилось с момента создания "функции" (или с момента последнего слияния). Таким образом, у вас все еще есть полная история, если у вас возник конфликт слияния.

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

git checkout main
git merge feature

См. rebase страница Понимание Git Концептуально для хорошего обзора