git: squash / fixup ранее коммит - PullRequest
       8

git: squash / fixup ранее коммит

24 голосов
/ 15 октября 2008

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

A-B-C

Теперь ваша сборка / тест не пройдена. Исправление должно быть объединено в А. Мой текущий рабочий процесс выглядит так:

$ git commit -m "fixA"

A-B-C-fixA

$ git rebase -i A~1

И исправление сквоша в A, результат:

A'-B-C

Есть ли команда, чтобы сделать что-то вроде:

A-B-C + (index with fix for A)

$ git commit -supperdupper A 

Результат:

A'-B-C

Ответы [ 6 ]

20 голосов
/ 05 января 2011

Если вы просто ищете простое решение для исправления предыдущих коммитов, прочитайте вопрос! Это все объясняет. Но так как Эльмарко просил скользкий путь, мы идем:

Начиная с Git 1.7.0, есть опция --autosquash для rebase, которая делает то, что вы хотите. Есть также опции --fixup и --squash для commit, чтобы упростить задачу. С помощью псевдонимов вы, вероятно, сможете объединить все это в одну команду.

Я бы предложил обновить до новейшего Git для максимальной удивительности:

git/Documentation/RelNotes $ grep -i -A1 autosquash\\\|fixup *
1.7.0.txt: * "git rebase -i" learned new action "fixup" that squashes the change
1.7.0.txt-   but does not affect existing log message.
--
1.7.0.txt: * "git rebase -i" also learned --autosquash option that is useful
1.7.0.txt:   together with the new "fixup" action.
1.7.0.txt-
--
1.7.3.txt: * "git rebase -i" peeks into rebase.autosquash configuration and acts as
1.7.3.txt:   if you gave --autosquash from the command line.
1.7.3.txt-
--
1.7.4.txt: * "git commit" learned --fixup and --squash options to help later invocation
1.7.4.txt-   of the interactive rebase.
--
1.7.4.txt: * "git rebase --autosquash" can use SHA-1 object names to name which
1.7.4.txt:   commit to fix up (e.g. "fixup! e83c5163").
1.7.4.txt-
3 голосов
/ 09 июля 2014

Мой текущий рабочий процесс git настолько интенсивен --fixup / --squash, что я написал новую команду git-fixup, которая автоматически обрабатывает большинство раздражающих битов:

  • git fixup показывает измененные файлы, сгруппированные по последним коммитам, которые касаются тех же файлов
  • git fixup -a фиксирует все эти изменения при --fixup изменениях с соответствующими «родительскими» коммитами
  • git fixup -r делает автоматический git rebase --autosquash для всех фиксаций фикса

Множество изменений таковы, что для выполнения работы достаточно только трех приведенных выше команд, без копирования-вставки коммит-идентификаторов или чтения через git log для поиска правильных --fixup целей.

Источник: https://github.com/ohmu/git-crust

2 голосов
/ 19 февраля 2013

I создал псевдонимы , чтобы упростить использование команд git commit --fixup и git commit --squash, добавленных в git 1.7. Добавьте их к вашему ~/.gitconfig:

[alias]
  fixup = !sh -c 'REV=$(git rev-parse $1) && git commit --fixup $@ && git rebase -i --autosquash $REV^' -
  squash = !sh -c 'REV=$(git rev-parse $1) && git commit --squash $@ && git rebase -i --autosquash $REV^' -

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

$ git commit -am 'bad commit'
$ git commit -am 'good commit'

$ git add .          # Stage changes to correct the bad commit
$ git fixup HEAD^    # HEAD^ can be replaced by the SHA of the bad commit

Плохой коммит может быть несколько коммитов назад.

2 голосов
/ 04 апреля 2011

Если вы хотите раздавить последние два коммита, вам нужно вызвать

git rebase --interactive <3rd last commit>

Затем вам нужно выбрать последний коммит и раздавить второй до последнего коммита. Вы не можете раздавить самый верхний коммит в истории.

0 голосов
/ 30 марта 2016

Я думаю, что корень проблемы в том, что git (и управление версиями в целом) заставляет вас думать с точки зрения последовательности изменений, но набор изменений или ветвь функций или как вы называете сплоченную группу связанных изменений в целом не логически последовательный. Порядок, в котором был написан код, является второстепенным и не обязательно связан с порядком, в котором он должен быть прочитан.

У меня нет решения, но я написал Perl-скрипт , чтобы помочь автоматизировать процесс переписывания истории. Он похож на скрипт Python @MikaEloranta, который я не видел, когда писал его.

commit --fixup и rebase --autosquash великолепны, но их недостаточно. Когда у меня есть последовательность коммитов A-B-C, и я записываю еще несколько изменений в мое рабочее дерево, которые принадлежат одному или нескольким из этих существующих коммитов, я должен вручную просмотреть историю, решить, какие изменения принадлежат тем или иным коммитам, подготовить их и создайте коммиты fixup!. Но у git уже есть доступ к информации, достаточной для того, чтобы сделать все это за меня.

Для каждого блока в git diff скрипт использует git blame, чтобы найти коммит, который последним коснулся соответствующих строк, и вызывает git commit --fixup, чтобы написать соответствующие fixup! коммиты, по сути, делая то же самое, что я делал вручную до этого.

Если сценарий не может разрешить ханк в однозначном коммите, он сообщит о нем как о неудачном ханке, и вам придется прибегнуть к ручному подходу для этого. Если вы дважды изменили строку в двух отдельных фиксациях, сценарий разрешит изменение в этой строке до самой последней из этих фиксаций, что не всегда может быть правильным разрешением. ИМХО в ветке функций «нормальной формы» вы не должны менять строку дважды в двух разных коммитах, каждый коммит должен представлять окончательную версию строк, к которой он прикасается, чтобы помочь рецензенту (-ам). Тем не менее, это может произойти в ветке с исправлениями ошибок, например, если строка foo(bar()); может быть затронута коммитом A (переименовать foo в fox) и коммитом B (переименовать bar в baz).

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

0 голосов
/ 15 октября 2008

То, что вы делаете, опасно, если вы делитесь веткой, в которую вносите изменения, с другими людьми. В вашем случае вы переписываете коммит A и перебираете B и C поверх нового A, который является совершенно новым объектом. Любой, кто уже вытащил старый А в свои репозитории, может испортить свой репозиторий, поскольку история в вашем репозитории будет «волшебным образом» изменена. Их мерзавец не мог знать, что история была переписана.

Из-за этого факта разработчики Git намеренно не сделали это легким делом, поскольку вы должны знать о последствиях выполнения такой операции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...