Найти, где источник разветвился от Git - PullRequest
8 голосов
/ 23 июня 2010

У меня есть репозиторий git (охватывающий более или менее историю проекта) и отдельные источники (просто тарбол с несколькими файлами), которые разветвились некоторое время назад (фактически где-то в 2004 или 2005 году).

Источники из tarball претерпели довольно много изменений, из которых я хотел бы включить некоторые. Теперь вопрос в том, как выяснить, что на самом деле было точкой ветвления для измененных источников, чтобы получить минимальное различие в том, что там произошло.

Так что я в основном хочу найти место в истории git, где код больше всего похож на архив исходных текстов, которые у меня есть. И я не хочу делать это вручную.

Стоит также упомянуть, что измененные источники содержат только подмножество файлов и разбили некоторые файлы на несколько. Однако код, который там находится, кажется, имеет только небольшие модификации и несколько дополнений.

Если вы хотите поиграть с этим сами, тарбол с источниками - здесь , а Git размещен на Gitorious : git://gitorious.org/gammu/mainline.git

Ответы [ 6 ]

4 голосов
/ 23 июня 2010

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

Лучше всего будет ограничиться определенными файлами.Если вы рассматриваете только один файл, это не займет много времени, чтобы перебрать все версии этого файла (используйте git rev-list <path>, чтобы получить список, так что вам не нужно тестировать каждый коммит).Для каждого коммита, который изменил файл, вы можете проверить размер diff и довольно быстро найти минимум.Сделайте это для нескольких файлов, надеюсь, они согласятся!

Лучший способ настроить себя для сравнения - сделать временный коммит, просто скопировав в свой tarball, чтобы вы могли иметь ветку с именемtarball для сравнения.Таким образом, вы можете сделать это:

git rev-list path/to/file | while read hash; do echo -n "$hash "; git diff --numstat tarball $hash path/to/file; done

, чтобы получить хороший список всех коммитов с их размерами различий (первые три столбца будут SHA1, количество добавленных строк и количество удаленных строк),Тогда вы можете просто передать его в awk '{print $1,$2+$3}' | sort -n -k 2, и у вас будет отсортированный список коммитов и их размеры различий!

Если вы не можете ограничиться небольшим количеством файлов для тестирования, яможет возникнуть искушение вручную реализовать что-то похожее на git-bisect - просто попытайтесь сузить свой путь до небольшого различий, делая предположение, что, по всей вероятности, коммиты, близкие к вашему лучшему случаю, также будут иметь меньшие разности, а коммиты далеки отэто будет иметь большие различия.(Где-то между методом Ньютона и полным бинарным / сеточным поиском, возможно?)

Редактировать: Другая возможность, предложенная в Дуглас 'ответ , если вы думаете, что некоторые файлы могут быть идентичный тем, которые есть в некоторых коммитах, состоит в том, чтобы хэшировать их с помощью git-hash-object, а затем посмотреть, какие коммиты в вашей истории имеют этот BLOB-объект.Есть вопрос с несколькими отличными ответами о том, как это сделать.Если вы сделаете это с несколькими файлами - желательно с частыми изменениями - вы сможете довольно быстро сузить целевой коммит.

2 голосов
/ 23 июня 2010

Не лучшее решение, но чтобы угадать, какие это могут быть ревизии: Предположим, что некоторые файлы в tar-архиве не были изменены, так как они были разветвлены.Запустите git hash object для каждого файла в tar-шарах, затем найдите эти файлы в хранилище, используя git show .Затем попробуйте найти коммиты, в которые были включены эти файлы, возможно, используя git whatchang .Тогда ответом на ваш вопрос может стать коммит с наиболее распространенными файлами, но он все равно будет немного удачным.

1 голос
/ 23 июня 2010

исходя из того, что araqnid сказал, что я придумал 9c6c864426bf88429e77c7e22b5aa78e9295b97a (только что попросили вещи между 0.61.0 и HEAD), это, вероятно, не самый лучший вариант) вы можете сделать лучше с чем-то вроде

git rev-list --no-merges --all | while read rev; do patchsize=$(git diff $rev | wc -c); echo $patchsize $rev; done | sort -n | less

при условии, что вы импортировали tarball в git и проверили эту ревизию (я сделал это, не пометив, а затем

git init
git add .
git commit -m "import tarball"
git remote add origin git://gitorious.org/gammu/mainline.git

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

0 голосов
/ 11 января 2013

Если у вас есть приблизительное представление о том, где произошла развилка, рассмотрите вариант использования git meld Уилла Мэнли. (См. Также: Просмотр различий веток с meld? .)

Чтобы сделать это, добавьте содержимое tarball в ваш репозиторий (что вы будете делать в любом случае). После установки Meld и git-meld запустите

git meld branch_from_tarball commit_to_check &

на разных коммитах, пока не найдете тот с наименьшими различиями. Эта команда открывает meld и просматривает изменения в дереве каталогов между указанными коммитами, при этом идентичные файлы скрыты. Пример скриншотов:

Мелд, показывающий два совершенно разных коммита:
Very different

Отображение двух похожих коммитов: Similar

0 голосов
/ 23 июня 2010

Импортируйте эти файлы в tar-архиве в git-ревизию, в отдельную ветку или совершенно новую: позиция на графе ревизий не важна, мы просто хотим, чтобы она была доступна в виде дерева.

Теперь для каждой ревизии в master, просто сделайте сравнение с этим деревом / ревизией («импортированными») и просто выведите, насколько велик diff. Что-то вроде:

git rev-list master | while read rev; do patchsize=$(git diff $rev imported | wc -c); echo $rev $patchsize; done

Таким образом, ревизия с наименьшим размером патча будет «ближайшей», по очень грубому эмпирическому правилу. (При одинаковой ревизии размер патча будет равен 0, а все остальное будет отличным от нуля, и чем больше изменено, тем больше).

0 голосов
/ 23 июня 2010

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

Вы должны быть в состоянии сделать это:

git remote add thefork git://wherever.it.lives/thefork.git

git fetch thefork

git branch -f thefork-branch thefork/branchname

git checkout thefork-branch

В этот момент вы можете запустить gitk и просмотреть полную историю разветвленной ветки и вашего локального репозитория, а также посмотреть, подключены они или нет.

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