2012-07-23 4 views
6

Я бы хотел рецепт для поиска дублированных изменений. Патч-идентификатор, вероятно, будет таким же, но атрибутов фиксации может и не быть.git find duplicate commits (by patch-id)

Это, как представляется, планируемое использование патч-ID:

мерзавец патч-идентификатор --help

IOW, вы можете использовать эту вещь, чтобы искать, вероятно, дубликата совершает.

Я полагаю, что нанизывания «журнал GIT», «мерзавец патч-ID» и Uniq может сделать работу плохо, но если кто-то имеет команду, которая делает работу хорошо, я ценю это.

+0

Это увлекательная функция. Из любопытства, как далеко в прошлом вы намереваетесь смотреть? Я видел, как некоторые творческие возможности интеграции для этого (т. Е. «Мой вкладчик не знает, как переустанавливать»), но в течение долгой истории это было бы менее эффективно ...? – Christopher

+0

Проблема появилась в недельной истории одной ветви, поэтому мой прецедент был довольно нежным (git log -p было достаточно). Комментарий патча-идентификатора мне любопытно, хотя ... Поиск всей истории может быть болезненным. – bsb

ответ

10

Поскольку повторяющиеся изменения, вероятно, не на одной и той же отрасли (кроме случаев, когда есть Возвращается между ними), вы можете использовать git cherry:

git cherry [-v] [<upstream> [<head> [<limit>]]] 

Где upstream будет ветвь для проверки дубликатов изменений в head.

2

У меня есть проект, который работает на игрушечном репо, но как он держит patch-> Зафиксировать карту памяти может иметь проблемы на больших РЕПО:

# print commit pairs with the same patch-id 
for c in $(git rev-list HEAD); do \ 
    git show $c | git patch-id; done \ 
| perl -anle '($p,$c)[email protected];print "$c $s{$p}" if $s{$p};$s{$p}=$c' 

Выход должен быть пар фиксаций с тем же патчем-id (3 дубликата ABC выходят как «AB», затем «BC»).

Изменить команду мерзавца преподобного списка, чтобы ограничить коммиты Проверили:

git log --format=%H HEAD somefile 

Append "| xargs GIT-шоу" для просмотра коммитов в деталях, или «| xargs мерзавец шоу -s --oneline "для резюме:

0569473 add 6-8 
5e56314 add 6-8 again 
bece3c3 comment 
e037ed6 add comment again 

оказывается, патч-ID не работает в моем случае, как оригинальный были дополнительные изменения, которые впоследствии совершающие. «git log -S» был более полезен.

+0

Если вы хотите посмотреть только на raw diff между commit и его родителем, вы можете сделать что-то вроде 'git diff $ c ~ 1 $ c | git patch-id'. Это будет неправильно вести слияния. После обоих слияний родители - более сложная проблема. – Christopher

+0

Похоже, что патч-идентификатор находит тот же самый diff? $ git diff HEAD ~ 1 HEAD | git patch-id 3318362fa07e580 .. 000000000000 .. $ git show ГЛАВНАЯ | git patch-id 3318362fa07e580 .. c397c4cdc426 .. – bsb

+0

@bsb Вы действительно хотите написать 'git show $ c | git patch-id'? 'git show' печатает метаданные, но' git patch-id' нуждается в патче в качестве ввода ... –

7

Для поиска дубликатов конкретной фиксации это может сработать для вас.

Во-первых, определить патч идентификатор цели фиксации:

$ THE_COMMIT_REF_OR_SHA_YOURE_SEEKING_DUPES_OF='7a3e67c' 
$ git show $THE_COMMIT_REF_OR_SHA_YOURE_SEEKING_DUPES_OF | git patch-id 
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 7a3e67ce38dbef471889d9f706b9161da7dc5cf3 

Первый SHA является патч-ID.Далее, список исправлений идентификаторы для каждой фиксации и отфильтровать этот матч:

$ for c in $(git rev-list --all); do git show $c | git patch-id; done | grep 'f6ea51cd6acd30cd627ce1a56e2733c1777d5b52' 
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 5028e2b5500bd5f4637531e337e17b73f5d0c0b1 
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 7a3e67ce38dbef471889d9f706b9161da7dc5cf3 
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 929c66b5783a0127a7689020d70d398f095b9e00 

Все вместе с несколькими дополнительными флагами, и в виде utility script: Использование

test ! -z "$1" && TARGET_COMMIT_SHA="$1" || TARGET_COMMIT_SHA="HEAD" 

TARGET_COMMIT_PATCHID=$(
git show --patch-with-raw "$TARGET_COMMIT_SHA" | 
    git patch-id | 
    cut -d' ' -f1 
) 
MATCHING_COMMIT_SHAS=$(
for c in $(git rev-list --all); do 
    git show --patch-with-raw "$c" | 
     git patch-id 
done | 
    fgrep "$TARGET_COMMIT_PATCHID" | 
    cut -d' ' -f2 
) 

echo "$MATCHING_COMMIT_SHAS" 

:

$ git list-dupe-commits 7a3e67c 
5028e2b5500bd5f4637531e337e17b73f5d0c0b1 
7a3e67ce38dbef471889d9f706b9161da7dc5cf3 
929c66b5783a0127a7689020d70d398f095b9e00 

это не очень быстрый, но для большинства рЕПО должны получить работу (только измеряется 36 секунд для репо с 826 фиксаций и 158MB .git дир на частоте 2,4 ГГц C руда 2 Duo).

+0

Я могу быть единственным смущенным, но на всякий случай «target-commit» не является буквальным; замените его на SHA фиксации, для которой вы хотите получить идентификатор патча. – Jimothy

+1

@Jimothy Yep, или имя ветки или имя тега (любой вариант, я думаю). Я посмотрю, смогу ли я сделать это немного яснее. –

2

щегольской команды, предложенной bsb требует несколько небольших ухищрений:

(1) Вместо git show, которая проходит git diff-tree --cc, команда должна использовать

git diff-tree -p 

В противном случае git patch-id генерирует паразитные нуль SHA1 хеши ,

(2) Когда используется труба до xargs, xargs должен иметь аргумент -L 1. В противном случае тройная фиксация не будет сопряжена с эквивалентной фиксацией.

Вот псевдоним идти в ~/.gitconfig:

dup = "!f() { for c in $(git rev-list HEAD); do git diff-tree -p $c | git patch-id; done | perl -anle '($p,$c)[email protected];print \"$c $s{$p}\" if $s{$p};$s{$p}=$c' | xargs -L 1 git show -s --oneline; }; f" # "git dup" lists duplicate commits 
0

Для поиска дубликатов фиксаций фиксации $hash, за исключением слияния совершает:

git rev-list --no-merges --all | xargs -r git show | git patch-id \ 
    | grep ^$(git show $hash|git patch-id|cut -c1-40) | cut -c42-80 \ 
    | xargs -r git show -s --oneline 

Для поиска дубликата слияния совершить $mergehash, замените $(git show $hash|git patch-id|cut -c1-40) выше одним из двух идентификаторов патча (1-й столбец), указанных git diff-tree -m -p $mergehash | git patch-id. Они соответствуют различиям в объединении с каждым из двух его родителей.

Чтобы найти дубликаты всех фиксаций, за исключением слияния совершает:

git rev-list --no-merges --all | xargs -r git show | git patch-id \ 
    | sort | uniq -w40 -D | cut -c42-80 \ 
    | xargs -r git log --no-walk --pretty=format:"%h %ad %an (%cn) %s" --date-order --date=iso 

Поиск дубликатов фиксаций может быть расширен или ограничено путем изменения аргументы git rev-list, который принимает многочисленные варианты. Например, чтобы ограничить поиск определенной веткой, укажите его имя вместо опции --all; или для поиска в последних 100 совершениях передают аргументы HEAD ^HEAD~100.

Обратите внимание, что эти команды бывают быстрыми, так как они не используют цикл оболочки, а пакетный процесс совершает.

Чтобы включить коммиляцию, снимите опцию --no-merges и замените xargs -r git show на xargs -r -L1 git diff-tree -m -p. Это намного медленнее, потому что git diff-tree выполняется один раз за фиксацию.

Пояснение:

  • Первая строка генерирует карту идентификаторов патча с совершающими хешами (данные 2-колонок, по 40 символов в каждом).

  • Вторая строка сохраняет только хэши фиксации (2-й столбец), соответствующие идентификаторам повторяющихся патчей (1-й столбец).

  • Последняя строка печатает пользовательские данные о дублировании.