Сквош только для одной "правильной" фиксации для запроса github pull

У меня есть репо на github, который кто-то еще (Боб, ради аргумента) выдал запрос на вытягивание. Его код не идеален, поэтому мы проходим через несколько раундов разметки. Насколько я понимаю, он совершает и подталкивает свой запрос на растяжение для каждого набора отмеченных изменений.

Итак, мой репозиторий теперь выглядит следующим образом:

master: ---o A (Chowlett
           |
           |
pull-req:  o---o---o---o
               B   C   D (all Bob)

Заключить SHA и msgs:

А:

123456 Good commit <chowlett>

В:

777ccc Fix the widget bug <bob>

С

888ddd Review markups <bob>

D:

999eee Further markups <bob>

Теперь я рад принять этот запрос на тягу; но я предпочел бы, чтобы версии с предварительной разметкой не были в моем репо. Могу ли я достичь всего следующего: и как?

  • Объединение B, C и D в мое репо как единый commit
  • Сгенерируйте "запрос на слияние слиянием № 99 в...".
  • Если github автоматически закрывает запрос на перенос

Ответ 1

Обратите внимание, что Бобу не нужно раздавить свои коммиты, когда он делает PR-программу GitHub.
С марта 2016 года вы можете оставить эту операцию сопровождающему (вы), принимающему ваш PR.

См. " Squash your commits" и его новая документация

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

https://help.github.com/assets/images/help/pull_requests/squash- и-merge.png

Ответ 2

В git есть две функции "squash". Существует git merge --squash и есть действие squash в git rebase --interactive. Первый не сохраняет никакой информации об авторе или дате, просто собирая все изменения из серии коммитов в локальную рабочую копию. Последнее раздражает, потому что оно требует взаимодействия.

Расширение git squash делает то, что вы хотите. Он переустанавливает текущий HEAD на заданную базу, автоматически сжимая фиксации между ними. Он также предоставляет параметр командной строки для установки сообщения на последнем сжатом коммита в случаях, когда rebase не создает конфликтов.

Бросьте это вместе с hub и ghi, вы можете построить script вдоль этих строк:

git pull upstream master
hub checkout https://github.com/$user/$repo/pull/$issue
git squash master
rev=$(git rev-parse --short HEAD)
git checkout master
git merge $rev
git commit --amend "Merged pull request #$issue"
git push upstream master
ghi close $issue $user/$repo
ghi comment $issue "Merged as $rev" $user/$repo 

Ответ 3

Вы можете использовать опцию -squash для слияния

git merge <remote url> <remote branch> --squash

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

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

Ответ 4

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

Одна идея заключалась бы в том, чтобы проверить, что ветка и сквош все зафиксированы в одном, используя iteractive rebase, а затем принудительно нажмите для обновления запроса на перенос и слияния (хотя часть этой работы может быть делегирована Бобу).

Чтобы автоматически вычеркнуть все коммиты из ветки в первую и применить это к запросу pull, вы можете использовать следующие команды:

$ git checkout pull-req
$ GIT_SEQUENCE_EDITOR='sed -i "2,\$s/^pick/s/g" $1' git rebase -i origin/master
$ git push --force

GIT_SEQUENCE_EDITOR является переменной среды git для установки временного редактора для списка фиксации переадресации. Мы устанавливаем его в встроенный script, который заменяет слово pick на s (что означает squash) в начале всех строк, кроме первого (что 2,\$ в шаблоне sed). Список фиксации, который передается в script, представляет собой простой текстовый файл. git затем перейдет к rebase и позволяет редактировать окончательное сообщение фиксации.

Кроме того, с помощью git hook вы могли бы более или менее легко отредактировать это окончательное сообщение в соответствии с вашими потребностями (например, добавьте визуальный разделитель между сообщениями раздавленных коммитов).

Использование git merge --squash

Скручивание также возможно через git merge --squash. См. здесь для разницы между этими двумя методами. Буква script вырезала бы фиксации ветки в одно коммит, используя команду merge. Он также создает резервную копию ветки (на всякий случай).

MAINBRANCH="master"    
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)

# update current feature branch with master
git pull origin $MAINBRANCH

# delete existing backup
git branch -D "$CURRENT_BRANCH-backup"

# backup current feature branch and go back
git checkout -b "$CURRENT_BRANCH-backup" && git checkout -

# checkout and update master branch
git checkout $MAINBRANCH && git pull

# create new branch from master
git checkout -b "$CURRENT_BRANCH-squashed"

# set it to track the corresponding feature branch
git branch "$CURRENT_BRANCH-squashed" --set-upstream-to "$CURRENT_BRANCH"

# merge and squash the feature branch into the one created
git merge --squash $CURRENT_BRANCH

# commit the squashed changes
git commit

# force push to the corresponding feature branch
git push -f . HEAD:$CURRENT_BRANCH

# checkout the feature branch
git checkout $CURRENT_BRANCH

# delete the squashed copy
git branch -D "$CURRENT_BRANCH-squashed"

Ответ 5

Это сработало для меня.

  • Моя работа над devtools_import_export остается неповрежденной.
  • Мой запрос на растяжение для issue35squashed для восходящего/ведущего имеет только одну фиксацию.
  • Увы, слияние не записывается, но сообщение commit имеет все подробности.

Вот что я на самом деле сделал (см. https://github.com/anaran/devtools-snippets/network)

git checkout master
git status # all clean
git checkout -B issue35squashed master
git merge --squash devtools_import_export
git status # looks good
git commit # review and commit via emacs
git log --graph --abbrev-commit --stat --pretty --decorate=full --branches
git push --all -v

(Моя предыдущая попытка с использованием git merge --no-ff ... находится в issue35take2, и запрос на перенос для нее содержит все отдельные коммиты из devtools_import_export. Нехорошо.)