Я думаю, что корень проблемы заключается в том, что мерзавец (и контроль версий в целом) заставляет вас думать в терминах последовательностей изменений, а набор изменений или функция Гиса или что вы называете сплоченная группа связанных изменений, как правило, не логически последовательна. Порядок, в котором был написан код, является случайным и необязательно связан с порядком, в котором он должен быть прочитан.
У меня нет решения, но я написал Perl script, чтобы помочь автоматизировать процесс перезаписи истории. Это похоже на Python-скрипт @MikaEloranta, который я не видел, когда писал.
commit --fixup
и rebase --autosquash
отличные, но они недостаточно. Когда у меня есть последовательность коммитов A-B-C
, и я пишу еще несколько изменений в моем рабочем дереве, которые принадлежат одному или нескольким из существующих коммитов, я должен вручную посмотреть на историю, решить, какие изменения принадлежат, в которой они совершают, сценивают и создают fixup!
совершает. Но git уже имеет доступ к достаточной информации, чтобы иметь возможность делать все это для меня.
Для каждого ломоть в git diff
скрипт использует git blame
найти коммит, который последним коснулся соответствующие строки, и призывает git commit --fixup
писать соответствующие fixup!
фиксаций, по сути делает то же самое я делал вручную раньше.
Если сценарий не может разрешить кусок для одного, недвусмысленного коммита, он сообщит об этом как об отказе, и вам придется вернуться к ручному подходу для этого. Если вы дважды изменили строку в двух отдельных коммитах, скрипт разрешит изменение этой строки до последней из этих коммитов, что может не всегда быть правильным разрешением. ИМХО в ветви функции «нормальной формы» вы не должны менять строку дважды в двух разных коммитах, каждая фиксация должна представлять финальную версию линий, к которой она прикасается, чтобы помочь рецензентам. Однако это может произойти в ветке bugfix, чтобы создать пример, который может быть затронут в строке foo(bar());
с помощью commit A (переименовать foo
на fox
) и совершить B (переименовать bar
в baz
).
Если вы считаете, что сценарий полезен, пожалуйста, не стесняйтесь улучшать и повторять его, и, возможно, однажды мы получим такую функцию в git
. Мне бы хотелось увидеть инструмент, который может понять, как конфликт слияния должен быть разрешен, когда он был введен с помощью интерактивной переустановки.
Почему такое странное требование, что fixA необходимо объединить в A? – 2008-10-15 12:26:47
, потому что он должен был быть в A в первую очередь. – elmarco 2008-10-15 14:27:54
Я делаю то же самое; Я не уверен, почему люди думают, что это странно. Если вы пытаетесь организовать коммиты на небольшие, логически сгруппированные фрагменты, то естественно готовить сразу несколько невыпущенных коммитов. (Возможно, вы не знаете, действительно ли вы сделаны с A, пока не закончите C). – andy 2008-10-20 06:32:15