Использование git filter-branch для удаления коммитов по их сообщению коммита - PullRequest
9 голосов
/ 30 декабря 2010

Простая версия:

Если у меня есть ветка "foo-555", с кучей коммитов с такими сообщениями:

  • Foo 555: бла
  • foo 123: бла-бла
  • foo 555: бла-бла-бла
  • foo 321: бла-бла

и я хочу удалить все коммиты, которые не начинаются с "foo 555:", есть ли способ сделать это с помощью git filter-branch (или любого другого инструмента в этом отношении)?

Оригинальная версия (более подробная):

В нашем репозитории есть соглашение, где каждое сообщение коммита начинается с определенного шаблона:

Redmine # 555: SOME_MESSAGE

Мы также делаем небольшую перебазировку, чтобы внести изменения потенциальной ветки релиза в ветку конкретной проблемы. Другими словами, у меня может быть ветвь "foo-555", но прежде чем я сливаю ее с веткой "pre-release", мне нужно получить любые коммиты, которые в пре-релизе есть, которых нет у foo-555 (так что foo- 555 может быстро перейти вперёд к предварительной версии).

Однако, поскольку предварительный выпуск иногда изменяется, мы иногда сталкиваемся с ситуациями, когда вы вносите коммит из предварительного релиза, но затем этот коммит позже удаляется из предварительного релиза. Легко идентифицировать коммиты, которые пришли из предварительной версии, потому что номер из их сообщения о фиксации не будет соответствовать номеру ветви; например, если я вижу «Redmine # 123: ...» в моей ветке foo-555, я знаю, что это не коммит из моей ветки.

Итак, теперь вопрос: я хотел бы удалить все коммиты, которые "не принадлежат" ветви; другими словами, любой коммит, который:

  • В моей ветке foo-555, но не в ветке pre-release (pre-release..foo-555)
  • Имеет сообщение о коммите, которое не начинается с "Redmine # 555"

но, конечно, "555" будет варьироваться от филиала к филиалу. Есть ли способ использовать фильтр-ветвь (или любой другой инструмент) для достижения этой цели? В настоящее время я вижу только один способ сделать это - выполнить интерактивную ребазирование ("git rebase -i") и вручную удалить все "плохие" коммиты.

Ответы [ 2 ]

9 голосов
/ 03 марта 2012

Вот быстрое решение, которое использует filter-branch вместо ребазинга.Там нет интерактивности или необходимости разрешения конфликтов.

git filter-branch --commit-filter '
    if [ `git rev-list --all --grep "<log-pattern>" | grep -c "$GIT_COMMIT"` -gt 0 ]
    then
        skip_commit "$@";
    else
        git commit-tree "$@";
    fi'  HEAD

Возможно, вы захотите затем очистить с помощью:

git reflog expire --expire=now
git gc --prune=now
5 голосов
/ 30 декабря 2010

Напишите скрипт для удаления строк с помощью Redmine #555:

#!/bin/sh

mv $1 $1.$$
grep -v 'Redmine #555' < $1.$$ > $1
rm -f $1.$$

Конечно, вы можете делать это так, как вы хотите (например, echo скрипт команд для ed).

Затем запустите перебазирование с EDITOR, установленным на ваш скрипт:

EDITOR=/path/to/script git rebase -i REVISION

Конечно, завершение не гарантируется - могут быть ошибки во время перебазирования, вызванные пропуском ревизий.,Вы все еще можете исправить их и git rebase --continue вручную.

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