Выясните, был ли проверен фиксатор git до или после другого коммита, переданного хэшам

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

С помощью git, используя хеши для своих коммитов, каков способ узнать, было ли совершение совершения до или после другого коммита?

Ответ 1

Вещи, как вы заметили, не так просты в Git. В частности, определение "до" и "после" нуждается в более подробном разъяснении.

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

git log -1 --format='%ci' <commit>

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

Чтобы избежать этих проблем, поговорите о том, является ли одно обязательство предком другого, а не тем, что оно происходит до или после него. В следующем графе фиксации B и C являются предками A, а B не является предком C и наоборот:

B    (master)
| C  (branch)
|/
A    (root)

Чтобы определить, является ли commit A предком фиксации B, используйте следующую команду (на основе статьи в git готов):

git rev-list <commitA> | grep $(git rev-parse <commitB>)

В первой части перечислены все коммиты, являющиеся предками commit A; вторая часть получает полный хэш фиксации B, а затем выполняет поиск в списке предков для этой фиксации. Если вы видите какой-либо вывод, commit A является предком commit B. Поменяйте аргументы на выполнение, если commit A вместо этого является предком commit B.

Эта вторая форма медленнее, но дает вам абсолютную уверенность в том, что одна фиксация является предком другого.

Ответ 2

git rev-list --count может помочь. Предполагая, что 110a187 наступает 4 фиксации до 5d41af1, тогда:

 $ git rev-list --count 110a187..5d41af1
4
 $ git rev-list --count 5d41af1..110a187
0

Таким образом, что-то вроде:

test $(git rev-list --count $a..$b) == 0 && \
       echo "$a is not an ancestor of $b"

Ответ 3

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

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

git show --format="%ci" <commit>

Ответ 4

Вы можете получить всю информацию о фиксации из журнала, который показывает хеш, автора, дату и комментарий:

git log

Вы можете вывести определенное время/дату фиксации из журнала фиксации. Что-то вроде:

git log -1 --format="%cd" <commit>

"% cd" дает вам дату в формате журнала, вы также можете:

  • % cD: стиль RFC2822
  • % cr: relative
  • % ct: временная метка UNIX
  • % ci: формат ISO 8601

Оттуда вы можете сделать некоторые сравнения с некоторыми сценариями, если вам нужно автоматизировать.

Ответ 5

git merge-base имеет флаг для этого. Он просто возвращает код выхода 0/1.

git merge-base --is-ancestor <commit> <commit>

Ответ 6

Если вы используете теги, вы можете сделать

git describe --tags

Это покажет вам, сколько коммитов со времени последнего тега.

Ответ 7

Со всеми замечаниями, упомянутыми @me_and, вы также можете попробовать:

git rev-list --no-walk commitA commitB

В выходных данных вы увидите предоставленные коммиты, отображаемые в обратном хронологическом порядке по времени коммита. Поэтому порядок предоставляемых коммитов не имеет значения (в отличие от идеи, предложенной @Douglas Bagnall).