git журнал только текущей ветки - без указания откуда она пришла (мастер ..) - PullRequest
0 голосов
/ 07 марта 2020

Мне известно о git log master... Я понимаю, что это показывает все коммиты в текущей ветви, которые не находятся в master. Однако при работе с несколькими долгоживущими ветвями это раздражает. Мой филиал отключен от master, develop, release-x.x.x, feature-blah? Кто знает! Я не знаю, я точно не помню.

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

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

У меня есть решение, и я опубликую его как ответ, но мне интересно, есть ли лучший способ.

Ответы [ 3 ]

2 голосов
/ 07 марта 2020

Ваш вопрос подразумевает концепцию коммита, «принадлежащего» ветви, или ветви, состоящей из коммитов. Возможно, именно так другие инструменты смотрят на мир, но git действительно не работает таким образом. Так как я понимаю, что вы хотите просматривать коммиты, я постараюсь ответить на вопрос в этом духе, но понимаю, что не будет никакого хорошего решения этой проблемы, потому что git сам не "помнит", какая ветвь "родитель" вашей ветви.

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

Проблемы с вашим ответом:

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

O -- x -- x -- x <--(master)
      \
       A -- B -- C -- D <--(your_branch)
             \
              x -- x <--(other_branch)

На этом рисунке - опять же, если мы предположим, что коммиты и ветки связаны так, как предлагает ваш вопрос, - вы бы увидели your_branch как A, B, C и D, верно? Но если вы дадите log исключений для баз слияний всех ветвей с your_branch, одна из баз слияний будет B, поэтому A и B будут исключены.

Это изображение также иллюстрирует, почему нет реального решения поставленной проблемы. Я использовал визуальные подсказки, чтобы подразумевать, что other_branch был создан из your_branch, а не наоборот, но что касается того, как git хранит свои данные, это изображение такое же, как и то, где your_branch считается быть созданным из other_branch

O -- x -- x -- x <--(master)
      \
       A -- B -- x -- x <--(other_branch)
             \
              C -- D <--(your_branch)

Так что ничто git магазины не может сказать, хотите ли вы видеть A и B или нет.

Я добавлю, даже если вы говорите «ах, но я никогда этого не делаю», возникает другая возможная проблема, если вы когда-нибудь объедините ветку с ее родителем, но затем продолжите работу над ней. Все коммиты до слияния будут исключены из вашего вывода.

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

Другой подход:

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

Даже тогда, если у вас есть боковые ветви, которые объединяются обратно в some_branch, вы увидите их. Вы могли бы смягчить это, дав log --first-parent, но затем, если вы объедините свою ветвь с чем-то другим, а затем быстро перенесете свою ветвь через это слияние, у вас возникнут еще большие проблемы.

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

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

0 голосов
/ 10 марта 2020

Этот метод более чистый, но, к сожалению, он будет работать только для новых веток в будущем.

По сути, мы храним "метаданные" о ветке, из которой пришла наша ветка. Мы храним его в конфигурации локального репозитория под branch.BRANCH_NAME.parent. Это лучше, чем использование тегов, так как это не загромождает нашу историю. Также git будет автоматически обрабатывать удаление при удалении ветви.

Мы можем «отправить параметры» псевдониму git, если мы используем в нем функцию. Сначала мы отметим текущую ветвь (как позже в скрипте это будет новая ветвь).

git make-branch foo сделает вашу ветку и отметит родителя. git log-my-branch сделает запись в журнал, а git rebase2 bar сбросит родительский элемент после его перезагрузки. Для них вы можете указать дополнительные параметры, но имя ветви должно быть первым.

.gitconfig

[alias]
    # ...other aliases...
    make-branch = "!f() { \
    parent=$(git rev-parse --abbrev-ref HEAD); \
        git switch -c ${1} && git config branch.$1.parent $parent ; \
    }; f"
    log-my-branch = !git log $(git config branch.$(git rev-parse --abbrev-ref HEAD).parent)..HEAD
    rebase2 = "!f() { \
        git rebase $@ && git config branch.$(git rev-parse --abbrev-ref HEAD).parent $1 ; \
    }; f"
0 голосов
/ 07 марта 2020

Это работает, но не просто. Там не может быть простой способ. Также я только на 99% уверен, что это правильно. В отличие от этот ответ работает для уже существующих ветвей.

Используя git merge-base, мы можем найти лучшего (т. Е. Самого последнего в истории) предка между двумя коммитами. Если мы запустим это между HEAD (текущая ветвь) и каждой другой ветвью, то мы найдем набор коммитов, где вещи разделены.

Ниже мы используем команду for-each-ref, так как это лучше для сценариев, и мы выполнить команду. Мы также отфильтровываем текущий коммит.

git for-each-ref --shell --format='git merge-base HEAD %(refname)' refs/heads/ | sh | sed /"$(git rev-parse HEAD)"/d

При использовании git log мы можем дать ему коммиты для включения истории, а те, которые в не включают историю. Поэтому, если мы скажем включить историю HEAD и , а не историю баз слияний, о которых мы упоминали ранее, то все коммиты будут доступны только текущей ветке. Ниже приведен пример, показывающий, как получить все из HEAD, но не из ABC и 123

git log HEAD ^ABC ^123

Используя этот псевдоним, мы можем получить то, что хотим. В нем слишком много кавычек, чтобы выяснить, как правильно их убрать, поэтому я просто вручную вставил его в ~/.gitconfig

.gitconfig

[alias]
    # ...other aliases...
    log-my-branch = !git log HEAD $(git for-each-ref --shell --format='git merge-base HEAD %(refname)' refs/heads/ | sh | sed /"$(git rev-parse HEAD)"/d | sed 's/^/^/' | tr '\n' ' ' )

Затем просто запустите git log-my-branch чтобы получить это. Вы также можете сделать git log-my-branch --graph --decorate, чтобы настроить его. Или, если хотите, укажите его в псевдониме.


Некоторые предостережения: если у вас есть локальные версии ветвей, ответвляющихся от вашей, то он будет вести себя странно.

Если вы хотите это делать с пультами, а затем удалить refs/heads/. Например, если у вас есть только локальный филиал вашего филиала, но есть пульты других. Не уверен, насколько это будет полезно.

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