Как определить ранее или позже совершает программно? - PullRequest
0 голосов
/ 30 октября 2018

Можно ли сравнивать коммиты git программно или с их целочисленными шестнадцатеричными значениями? Более поздние коммиты больше целого, чем предыдущий? Так, например, если мы можем получить хэши в псевдокоде

int commit_a = myrepo.getCurrentCommit();
int commit_b = myrepo.getPreviousCommit();

if(commit_a > commit_b)
printf("Commit A is later than Commit B");
else
printf("Commit B is later than Commit A");

ПРИМЕЧАНИЕ: я отредактировал свой вопрос, чтобы спросить, есть ли библиотеки git, которые могут сделать приведенный выше пример. Или как реализовать свой.

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

фиксирует в Git форму направленного ациклического графа или DAG.

В любом графе у нас есть список смежности (поскольку граф определяется как G = ( V , E ), где V и E - наборы вершин и ребер соответственно): любая заданная вершина / узел в графе находится либо на расстоянии одного шага от другой вершины, через какое-либо ребро, либо дальше или не связана в все:

  C--D
 /
B------E  G--H
 \    /
  A  F

Узел A подключается к B (и наоборот), B подключается к C и E и так далее. G и H соединяются друг с другом, но не с остальной частью графа, поэтому этот граф состоит из двух непересекающихся подграфов. (Эти ребра не имеют направления.)

На графике , направленном , существует понятие предшественник и преемник , поскольку каждое соединение имеет стрелку:

A->B->C
   |
   v
   D

Здесь A соединяется с B, а B соединяется с C и D. Таким образом, B является преемником A, а C и D являются преемниками B (но не связаны друг с другом). С точки зрения предшественников, A является предшественником B, а B является предшественником как C, так и D.

Если график не имеет циклов - это ациклический - мы можем выполнить операцию транзитивного замыкания, используя операции предшественника / преемника. График Git направлен и ациклически - это DAG - так что мы можем сделать это с Git.

Внутри Git стрелки на самом деле задом наперед (по причинам реализации), но мы все еще выполняем то же транзитивное замыкание. Когда мы делаем это, мы обнаруживаем, что A является предком B, C и D:

A <-B <-C
    ^
    |
    D

потому что мы можем начать с любого из этих коммитов и вернуться обратно к A. B является предком C и D. Противоположное отношение потомок: D является потомком A.

Здесь нужно быть немного осторожнее. Между C и D. нет отношений предков или потомков, то есть C не является предком D, но C также не является потомком D. Вы не можете просто сказать «не предок, следовательно, потомок»: эти двое могут просто не относиться друг к другу. Это также верно для некоторых коммитов, если DAG имеет непересекающиеся подграфы, что допускается:

A <-B <-C   <-- master1

D <-E   <-- master2

Хотя D является предком E, D не имеет отношения ни к одному из A, B или C.

В любом случае команда Git, которая проверяет «предок»:

git merge-base --is-ancestor

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

hash1=$(git rev-parse $thing1^{commit}) || die "$thing1 does not name a git commit"
hash2=$(git rev-parse $thing2^{commit}) || die "$thing2 does not name a git commit"
if git merge-base --is-ancestor $hash1 $hash2; then
    echo "$thing1 is an ancestor of $thing2"
else
    if git merge-base --is-ancestor $hash2 $hash1; then
        echo "$thing1 is a descendant of $thing2"
    else
        echo "$thing1 and $thing2 are not relatable"
    fi
fi

Ответ «не относящийся к делу» возникает потому, что, как мы видели выше, мы получаем только частичный заказ , а не общий заказ от нашего предшественника / понятие преемника.

(Для целей Git коммит является собственным предком, поэтому git merge-base --is-ancestor $hash1 $hash1 всегда верен.)

0 голосов
/ 30 октября 2018

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

Однако каждому коммиту присуще достаточно информации, чтобы определить историю этого коммита, поэтому вы можете сравнить коммиты на основе истории. Есть довольно солидный вопрос и ответ о том, как это сделать уже: Как я могу определить, является ли один коммит потомком другого коммита?

...