2016-11-28 25 views
0

Мне нужно очистить 20 коммитов в строке от истории git в голом репозитории. Я пытаюсь использовать следующую команду (обратите внимание, я не хочу писать полнометражные хэшей и попытаться использовать сравнение подстроки):Как использовать --commit-filter, чтобы исключить 20 commit в один проход git filter-branch?

git filter-branch -d /dev/shm/scratch --commit-filter ' 
if [ ${GIT_COMMIT0:7} = e687d59 ] || 
    [ ${GIT_COMMIT0:7} = 58daf29 ] || 
    ... 
    [ ${GIT_COMMIT0:7} = 682b2c2 ] || 
    [ ${GIT_COMMIT0:7} = 947db9e ]; 
    then 
      skip_commit "[email protected]"; 
    else 
      git commit-tree "[email protected]"; 
    fi' --tag-name-filter cat -- --all 

Но я сразу же получить сообщение как:

Переработанный 414840693169a74d052548c7a7a1bc5b06d3b79c (1/10360) (0 секунд прошло, оставаясь 0 предсказаны) мерзавец совершают-дерево: 49: мерзавец фиксации дерева: Плохая замена не мог писать переписано фиксации

Сложно ошибаться либо с условием ИЛИ, либо с подстроками, я не могу понять.

У меня также есть дополнительный вопрос: как я могу получить файл журнала с отображением старого хеша на новый, когда git filter-branch завершил работу?

ответ

1

Основная проблема заключается в том, что это:

if [ ${GIT_COMMIT0:7} = e687d59 ] || 
    [ ${GIT_COMMIT0:7} = 58daf29 ] || 
    ... 
    [ ${GIT_COMMIT0:7} = 682b2c2 ] || 
    [ ${GIT_COMMIT0:7} = 947db9e ]; 

неправильный.

Синтаксис bash для подстрок равен ${name:offset:length}, который в этом случае будет ${GIT_COMMIT:0:7}, то есть вам не хватает двоеточия.

Но:

  • git filter-branch является ш (не Баш) сценарий;
  • сценарий фильтра-фильтра использует eval; и
  • Это не самый лучший способ сделать это в любом случае.

Первые два означают, что вы не можете полагаться на синтаксис, специфичный для bash.

Третье означает, что для этого нет реальной причины.

Одним из вариантов является использование оператора -o (или) программы [ (ака test):

if [ $GIT_COMMIT = ... -o 
    $GIT_COMMIT = ... -o 
    ... 
    $GIT_COMMIT = ... ]; then 

, но это все еще слишком болезненным, на мой взгляд. Вместо этого, почему бы не использовать grep, например .:

if echo $GIT_COMMIT | grep -F -f /tmp/list >/dev/null; then 

где файл /tmp/list содержит идентификаторы, которые вы хотите пропустить? Если grep находит один из них, он выходит с нулевым (успешным) статусом, в противном случае он выходит с ненулевым статусом (отказом), так же, как программа test или [ завершает работу 0, если тест преуспевает, или отличное от нуля, если он терпит неудачу.

(Если Grep имеет -q, вы можете использовать его, а не перенаправлять на /dev/null.)

0

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

  1. Подстроки должно быть ${GIT_COMMIT:0:7}, а не ${GIT_COMMIT0:7} (двоеточие после имени переменной)

  2. --tag-name-filter cat -- --all Вместо того, чтобы использовать HEAD. man page дает соответствующий пример:

    Для удаления коммитов автора «DARL McBribe» из истории:

    git filter-branch --commit-filter ' 
         if [ "$GIT_AUTHOR_NAME" = "Darl McBribe" ]; 
         then 
           skip_commit "[email protected]"; 
         else 
           git commit-tree "[email protected]"; 
         fi' HEAD 
    
       ^^^^ 
    

    Обратите внимание, что определение HEAD достаточно, чтобы очистить хранилище в том, что пример.

  3. Используйте bash тесты вместо test(1) (должно быть быстрее, и надежнее):

    if [[ ${GIT_COMMIT0:7} = e687d59 || ${GIT_COMMIT0:7} = 58daf29 || ... ]]; then 
    
+1

Только с помощью 'HEAD' плохо, если есть и другие отрасли, которые ответвляются _после_ переписанной истории , – j6t

+0

@ j6t Спасибо за подсказку – cxw

2

Я пишу это как

git filter-branch -d /dev/shm/scratch --commit-filter ' 
    case $GIT_COMMIT in 
    e687d59*|58daf29*|682b2c2*|947db9e*) 
     skip_commit "[email protected]" 
     ;; 
    *) 
     git commit-tree "[email protected]" 
     ;; 
    esac' --tag-name-filter cat -- --all 

Это не намного лучше, чем ваше заявление (после того, как у вас есть зафиксировал его как указано), но все же немного меньше печатает.

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

... --tag-name-filter cat -- --all --not that_commit 

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

  • Нет связанных вопросов^_^