Git псевдоним не регистрирует только ветку я хочу

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

Мой псевдоним выглядит так:

test = "!git log \"$(git rev-parse --abbrev-ref HEAD)\""

но когда я печатаю git test я получаю 2 коммитов на ветке плюс все предыдущие коммиты из разных веток (чего я не хочу).

Любая идея? Спасибо

1 ответ

Решение

Ваш псевдоним, как показано здесь, не является ошибочным, это ваше ожидание (ваша идея о том, что Git означает "на ветке"), что это неправильно: то, что вы подразумеваете под "на ветке", и что Git означает "на ветке" филиал ", просто не согласен.

Основная проблема в том, что ветки Git не означают то, что люди ожидают от них. (Можно утверждать, что это означает, что Git неверен. Некоторые другие VCS, такие как Mercurial, определяют ветви так, как вы хотите, чтобы Git определял их.) В Git имя ветви указывает только на один коммит, который Git вызывает коммит tip эта ветка.

Однако каждый коммит указывает на некоторое количество (обычно один) предыдущих или родительских коммитов. Git использует это для объединения коммитов во многих целях, в том числе показывая их с git log, Мы можем нарисовать это, на бумаге или на доске или в ответе Stackru, нарисовав имя ветви со стрелкой, выходящей из него, указывая на последний коммит, содержащийся внутри ветви, и затем получив этот коммит - чье "истинное имя" "это один из тех больших уродливых хеш-идентификаторов коммитов, но мы будем использовать здесь одну букву - со стрелкой из нее, указывающей на его родителя, и так далее:

... <-F <-G <-H   <-- master

Какие git log действительно начинается с коммита, на который указывает имя ветви, и показывает его. Затем он перемещается к родителю коммита и показывает это. Затем он движется дальше во времени (влево) и показывает, что совершает, и так далее. 1

Все внутренние ссылки Git всегда обратные, поэтому, пока мы размещаем новые коммиты вправо, нам не нужно рисовать внутренние стрелки. Мы просто знаем, что они идут задом наперед. Итак, давайте нарисуем более сложную установку:

...--F--G--H   <-- master
            \
             I--J   <-- feature

Имя feature указывает на фиксацию J так что делаете J находится на ветке функций. совершить J указывает на I, который указывает на H, который указывает на G, и так далее. Так что каждый коммит находится на ветке feature, хотя совершать H также верхушка коммит ветки master, Совершает через H все на master, так совершает через H находятся на обеих ветках.

Что вы хотите сделать здесь, вместо того, чтобы регистрировать все коммиты, содержащиеся в вашей текущей ветке - для чего простое git log достаточно - попросить Git записать коммиты, которые содержатся в вашей текущей ветке, но не содержатся в какой-то другой ветке (ветках). Сложность состоит в том, чтобы выяснить, как исключить эти коммиты.

Один из способов - перечислить каждое имя ветки, затем удалить текущее имя ветки, а затем сказать git log: Перечислить для меня каждый коммит, содержащийся в текущей ветке, начиная с HEAD , но остановите перечисление при достижении любого коммита, содержащегося в любой другой ветке Чтобы сделать это, вы можете получить текущее имя ветви (как вы делаете сейчас, или каким-либо другим способом) и исключить его из списка всех ветвей (что бы вы получили каким-то образом):

git log HEAD --not br1 br2 br3 br4

(если названы остальные четыре ветви br1 через br4).

Это обычно не обязательно, хотя. В общем, когда вы работаете с какой-то веткой, вы назначаете другое имя, иногда другое имя ветви, иногда имя для удаленного отслеживания, например origin/master - как текущая ветка вверх по течению. Каждая ветвь может иметь только одну восходящую настройку (или вообще не иметь настройки), и как только у вас будет восходящая установка, вы можете использовать символическую запись @{upstream} или короткая версия @{u} сослаться на это:

git log HEAD --not @{u}

Для этого существует более короткий синтаксис, потому что он очень полезен: добавление префикса коммита в шапку ^ символ означает "не", поэтому вы можете написать:

git log HEAD ^@{u}

а затем есть еще более короткий синтаксис, потому что это так часто встречается:

git log @{u}..HEAD

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

Так что вы, вероятно, хотите, это просто @{u}..HEAD нотации. Это не то же самое, что явное исключение всех других веток. Предположим, например, что у нас есть график, который выглядит частично так:

       M   <-- origin/br2
      /
...--H   <-- origin/master, origin/br1
      \
       I--J   <-- br1
           \
            K--L   <-- br2 (HEAD)

Предположим далее, что вверх по течению для br2 является origin/br2, Прося коммитов в origin/br2..br2 (То есть, @{u}..HEAD) означает, что вы будете выбирать коммиты L, K, J, а также I, Запрашиваемая коммитов, которые содержатся в br2 но нет другой ветки (т.е. нет br1) получит только L а также K, Если это - становится просто L а также K - это то, что вы хотите, тогда вам действительно нужно перечислить все ветви.

(Хитрость для перечисления всех ветвей заключается в использовании git for-each-ref с refs/heads/ префикс. Вы должны рассмотреть возможность использования git symbolic-ref читать текущее имя ветки, если вы собираетесь написать много сценариев или причудливых псевдонимов. Эти команды, git for-each-ref а также git symbolic-ref Это то, что Git называет сантехническими командами, предназначенными для написания сценариев и сложных псевдонимов. Они ведут себя более строго определенным образом, ориентированным на использование компьютера, по сравнению с "ориентированными на пользователя" командами, такими как git log или же git diff, Называть их "ориентированными на пользователя" немного смешно, но они явно более ориентированы на пользователя, чем, например, git diff-tree.)


1 Это немного упрощено. В случае просмотра более одного имени ветви или после фиксации слияния с несколькими родителями, git log должен линеаризовать топологию графа как-то. Это делается через очередь приоритетов, показывая следующий коммит с "наивысшим приоритетом" и добавляя в очередь родителей этого коммита. Однако для простых линейных цепочек достаточно идеи, что Git движется в обратном направлении по истории.

Другие вопросы по тегам