Извлечение только диапазона коммитов, которых нет в базовой ветке - PullRequest
0 голосов
/ 14 января 2019

Я бы хотел получить только коммиты branchA, отсутствующие в его базе branchB.

Например, рассмотрим эту историю:

B1 - B2 - B3 - B4 - B5
           \
            A1 - A2 - A3

Я бы хотел получить только A1, A2 и A3. Важно отметить, что я заранее не знаю, какой коммит A1 и сколько коммитов мне нужно получить. Мой вклад - это просто главы двух ветвей, в этом примере branchA=A3 и branchB=B5. Основываясь на таком вводе, мне нужно идентифицировать A1 и извлечь все между A1 и branchA, и в идеале ничего больше.

В качестве альтернативы, может быть интересен выбор минимального набора коммитов, который включает A1, A2 и A3 и достаточно информации для идентификации A1, также может быть интересным.

Почему? В случае использования, когда мне нужны только эти коммиты («что изменилось в branchA относительно branchB), выборка большего количества необходимых коммитов замедляет мой процесс. Возьмите, например, большой репозиторий с тысячами коммитов и ветвями функций только с несколькими коммитами. Извлечение всей истории branchA и branchB извлекает много коммитов, которые мне не нужны, и занимает много времени и пропускную способность сети.

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

git clone --depth 1 "$repo" --branch "$branchA" shallow
cd shallow

for ((depth = 8; depth <= 1024; depth *= 2)); do
    echo "trying depth $depth ..."
    git fetch --depth $depth
    git fetch --depth $depth origin "$branchB:$branchB"
    lastrev=$(git rev-list --reverse "$branchB" | head -n1)
    if git merge-base --is-ancestor "$lastrev" HEAD; then
        echo "found with depth=$depth"
        break
    fi
done

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

Есть ли лучший способ, чем этот? Я ищу чистое решение Git, но если в GitHub API есть что-то, чтобы сделать это быстрее и проще, это тоже может быть интересно.

1 Ответ

0 голосов
/ 15 января 2019

Сегодня это невозможно. Варианты вашего обходного пути - лучшее, что вы можете сделать.

В протоколе нет ничего, что помешало бы вам предоставить необработанный хэш-идентификатор вместо --depth аргумента для git fetch, который бы указывал git fetch на , притворяясь , что правильно --depth (что бы это ни было) было предоставлено. Но в git fetch также нет ничего, чтобы реализовать это. Следовательно, единственный способ сделать это - перечислять коммиты, по одному, назад от каждого кончика ветви, пока вы не найдете правильный хэш (ы), который также говорит вам, каким аргументом --depth должен быть ваш git fetch команда.

Однако к тому времени, когда вы перебрали достаточное количество хеш-идентификаторов, чтобы найти правильную глубину, в большинстве случаев вы могли бы просто выполнить полный клон. Таким образом, очень мало давления для реализации этой функции за пределами Git (например, через интерфейс GitHub). И присвоение имен коммитами с помощью хеш-идентификаторов также не доставляет никакого удовольствия людям - поэтому очень мало давления (или смысла) добавлять эту функцию к git fetch, либо.

Лучшим решением было бы то, в котором вы можете представить в другой репозиторий Git начальный хеш (который ваш собственный Git может предоставить путем локального преобразования имени в хэш): если вы в последний раз видели это кончик их B ветви был, скажем, B4, так что ваш собственный origin/B идентифицирует коммит B4, вы могли бы локально выполнить ( заметьте, что предложенный аргумент --depth-inferred-from не существует сегодня ):

git fetch --depth-inferred-from=origin/B A

который будет иметь ваш Git:

  1. run git ls-remote или эквивалент, который git fetch всегда запускает
  2. конвертирует их refs/heads/A (которые вы намереваетесь получить) в хеш-идентификатор, обозначаемый H на шаге 3
  3. попросить, чтобы их Git перечислили только <hash-of-B4>..H при представлении коммитов во время have сеанса
  4. добавьте остаток от обычной выборки, то есть сеанс have / want для получения идентификаторов объектов для выборки

Шаг 3, однако, требует новой функции в протоколе выборки, поэтому он очень нетривиален.

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