API GitHub - как сравнить 2 коммита

Можно получить список измененных файлов между двумя коммитами. Что-то вроде того сравнение двух коммитов в веб-версии, но используя GitHub Api.

Ответ 1

Официальный API сравнения коммитов: Сравнить два коммита:

GET /repos/:owner/:repo/compare/:base...:head

И :base, и :head могут быть именами ветвей в: repo или именами ветвей в других репозиториях в той же сети, что и :repo. В последнем случае используйте формат user:branch:

GET /repos/:owner/:repo/compare/user1:branchname...user2:branchname

Обратите внимание, что вы также можете использовать теги или фиксировать SHA. Например:

https://api.github.com/repos/git/git/compare/v2.2.0-rc1...v2.2.0-rc2

Обратите внимание на "...", а не ".." между двумя тегами.
И вам нужно сначала иметь самый старый тег, а затем новый.

Это дает статус:

  "status": "behind",
  "ahead_by": 1,
  "behind_by": 2,
  "total_commits": 1,

И для каждого коммита информация о файлах:

"files": [
    {
      "sha": "bbcd538c8e72b8c175046e27cc8f907076331401",
      "filename": "file1.txt",
      "status": "added",
      "additions": 103,
      "deletions": 21,
      "changes": 124,
      "blob_url": "https://github.com/octocat/Hello-World/blob/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt",
      "raw_url": "https://github.com/octocat/Hello-World/raw/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt",
      "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/file1.txt?ref=6dcb09b5b57875f334f61aebed695e2e4193db5e",
      "patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"
    }
  ]

НО:

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

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

Ответ 2

Изучая ответы, поступающие с официальным API, можно найти едва упоминаемый способ получения различий от Github. Попробуйте это:

  wget -H 'Accept: application/vnd.github.v3.diff' \
    http://github.com/github/linguist/compare/96d29b76...a20631af.diff
  wget -H 'Accept: application/vnd.github.v3.diff' \
    http://github.com/github/linguist/compare/a20631af...96d29b76.diff

Это ссылка, которую вы предоставили в качестве примера, с добавлением .diff. И обратный дифференциал такой же.

Данный заголовок гарантирует, что запрос обрабатывается API Github v3. Это в настоящее время по умолчанию, но может измениться в будущем. См. Типы носителей.

Почему две загрузки?

Github обслуживает линейные различия только от старых версий к новым. Если запрошенный diff действительно линейный и от более старой к более новой версии, вторая загрузка будет пустой.

Если запрашиваемый diff является линейным, но от более новой к более старой версии, первая загрузка будет пустой. Вместо этого весь diff находится во второй загрузке. В зависимости от того, чего вы хотите достичь, его обычно можно применить к более новой версии или применить обратно (patch -R) к более старой версии.

Если между парой запрошенных коммитов нет линейных отношений, обе загрузки получают ответы с ненулевым контентом. Один от общего предка до первого коммита, а другой - от одного общего предка до другого коммита. Нормальное применение одного различий, а другой обратный дает то же, что и применение вывода git diff 96d29b76..a20631af.

Насколько я могу судить, эти необработанные различия не подлежат ограничениям Github API. Запросы на 540 коммитов с 1002 изменениями файлов прошли без проблем.

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

Ответ 3

Ответ Traumflug неверен, если вы используете API для доступа к закрытым репозиториям. На самом деле, я думаю, что для ответа не требуется заголовок, так как в любом случае он работает без него в публичном репо.

Вы не должны помещать .diff в конце URL, и вы должны использовать поддомен api. Если вам нужен именно этот diff, вам нужно всего лишь добавить в запрос соответствующий заголовок медиа-типа (и токен для аутентификации).

Так, например:

  wget -H 'Accept: application/vnd.github.v3.diff' \
    https://api.github.com/repos/github/linguist/compare/96d29b76...a20631af?access_token=123

Документация Gitlab очень запутанная, поскольку в ней говорится, что она работает только для имен веток, но она также принимает commit shas. Кроме того, возвращаемый JSON включает в себя diff_url, который является просто прямой ссылкой на diff, но не работает, если репозиторий является закрытым, что не очень полезно.

Ответ 4

Вот еще один фактический исполняемый пример с использованием ссылок HEAD и HEAD~1 в моем общедоступном репо DataApp - ParamCompare, который должен помочь осветить нотации :owner и :repo, однажды замененные чистыми параметрами.

curl -X GET  https://api.github.com/repos/jxramos/DataApp--ParamCompare/compare/HEAD~1...HEAD

Для проверки работоспособности эквивалентное представление браузера можно увидеть на https://github.com/jxramos/DataApp--ParamCompare/compare/HEAD~1...HEAD

В общем случае форма выглядит следующим образом для предоставления альтернативного синтаксиса параметров для маршрутизации API:

https://api.github.com/repos/<owner_name>/<repo_name>/compare/HEAD~1...HEAD

Можно также вызвать URL-адрес, например

https://api.github.com/repos/jxramos/DataApp--ParamCompare/compare/80f0bb42606888ce7fc66b4402fcc90a1709c9e8...255fe089543f5569f90af54168af904e88fc150f

Должен быть эквивалентный graphql, чтобы просто урезать и выбрать эти результаты в списке files, чтобы выбрать все значения filename для передачи чего-либо типа вывода git diff --name-only прямо из удаленный. Я обновлю этот ответ, если выясню.