2008-10-15 3 views
23

Предположим, у вас есть:мерзавец: сквош/Fixup ранее совершить

A-B-C 

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

$ git commit -m "fixA" 

A-B-C-fixA 

$ git rebase -i A~1 

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

A'-B-C 

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

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

$ git commit -supperdupper A 

Результат:

A'-B-C 
+1

Почему такое странное требование, что fixA необходимо объединить в A? – 2008-10-15 12:26:47

+9

, потому что он должен был быть в A в первую очередь. – elmarco 2008-10-15 14:27:54

+4

Я делаю то же самое; Я не уверен, почему люди думают, что это странно. Если вы пытаетесь организовать коммиты на небольшие, логически сгруппированные фрагменты, то естественно готовить сразу несколько невыпущенных коммитов. (Возможно, вы не знаете, действительно ли вы сделаны с A, пока не закончите C). – andy 2008-10-20 06:32:15

ответ

19

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

На 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- 
0

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

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

2

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

git rebase --interactive <3rd last commit> 

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

1

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

[alias] 
    fixup = !sh -c 'REV=$(git rev-parse $1) && git commit --fixup [email protected] && git rebase -i --autosquash $REV^' - 
    squash = !sh -c 'REV=$(git rev-parse $1) && git commit --squash [email protected] && 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 

Дурные фиксации может быть несколько совершает назад.

3

Мой текущий поток мерзавец работа настолько --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

0

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

У меня нет решения, но я написал 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. Мне бы хотелось увидеть инструмент, который может понять, как конфликт слияния должен быть разрешен, когда он был введен с помощью интерактивной переустановки.

Смежные вопросы