Журнал Git, щоб отримати комісії лише для певної гілки


214

Я хочу перерахувати всі комісії, які є лише частиною конкретної галузі.

З наступним, він перераховує всі комісії з гілки, але також від батьків (головного)

git log mybranch

Іншим варіантом, який я знайшов, було виключення об'єктів, доступних майстром, і дає мені те, що я хочу, але я хотів би уникнути необхідності знати назви інших гілок.

git log mybranch --not master

Я намагався використати git for-each-ref, але він також містить список моїх галузей, тому насправді він виключає всі:

git log mybranch --not $(git for-each-ref --format '^%(refname:short)' refs/heads/)

Оновлення:

Я тестую новий варіант, який я знайшов деякий час тому, і дотепер здається, що це могло бути те, що я шукав:

git log --walk-reflogs mybranch

Оновлення (2013-02-13T15: 08):

Опція --walk-reflogs хороша, але я перевірив, чи є термін дії рефлогів (за замовчуванням 90 днів, gc.reflogExpire ).

Я думаю, що знайшов відповідь, яку шукав:

git log mybranch --not $(git for-each-ref --format='%(refname)' refs/heads/ | grep -v "refs/heads/mybranch")

Я просто видаляю поточну гілку зі списку доступних гілок і використовую цей список для виключення з журналу. Таким чином я отримую лише ті комітети, які досягаються лише моїми галузями .


можна дублювати з stackoverflow.com/questions/53569
StarPinkER

Я вже бачив це питання, але не те саме
dimirc

2
Ви впевнені, що саме цього ви хочете? Я вважаю, що краще мати на увазі ціль: "що на моїй гілці, що не знаходиться у верхньому руслі", або "що на моїй гілці, що не в господарях". Плюс, хоча git швидко обрізається, це стає дорожче, оскільки у вас є більше гілок. У мене є сценарій, який я використовую, коли я називаю "git missing" після команди "відсутні" bzr. Ви можете знайти його тут: github.com/jszakmeister/etc/blob/master/git-addons/git-missing .
Джон Сакмайстер

1
Мені це справді потрібно для гачка після отримання, тому "майстер" не повинен завжди виключати гілку
dimirc

Так, дублікат, згаданий StarPinkER, працював для мене добре: git log $ (git merge-base HEAD branch) .. гілка
charo

Відповіді:


165

З того, що вам здається, ви повинні використовувати cherry:

git cherry -v develop mybranch

Це показало б усі документи, які містяться в моїй галузі , але НЕ в розробці . Якщо ви залишите останню опцію ( mybranch ), вона замість цього порівняє поточну гілку.

Як зазначав VonC, ви завжди порівнюєте свою філію з іншою галуззю, тож знайте свої гілки, а потім вибирайте, з якою слід порівняти.


4
Це саме те, що мені було потрібно, але здається, що для цього повинна бути більш інтуїтивна команда (так, навіть у світі Git).
Сет

12
Ви також git cherry -v masterможете порівняти поточну гілку з основною гілкою.
Пітікос

2
Небезпека використання git cherry полягає в тому, що коміти зіставляються лише у тому випадку, якщо їхній файл відрізняється між гілками. Якщо було б зроблено якесь об'єднання, яке зробило б різницю між однією гілкою та іншою, то git cherry розглядає їх як різні коміти.
Бен

Це просто дає мені fatal: Unknown commit mybranch.
Метт Арнольд

1
@MattArnold ви повинні змінити текст «розвивати» і «mybranch» в галузь , які існують на вашому репо
смайли

40

Але я хотів би уникнути необхідності знати назви інших гілок.

Я не думаю, що це можливо: філія в Git завжди базується на іншому або, принаймні, на іншій комісії, як пояснено в " git diff не вистачає ":

введіть тут опис зображення

Вам потрібна опорна точка для вашого журналу, щоб відобразити правильні зобов’язання.

Як згадувалося в " GIT - звідки я відділився? ":

гілки - це просто вказівки на певні комісії в DAG

Тож навіть якщо git log master..mybranchце одна відповідь, вона все одно показуватиме занадто багато комітів, якщо mybranchвона базується на myotherbranchсамій master.

Для того, щоб знайти цю посилання (походження вашої гілки), ви можете лише проаналізувати фіксації та побачити, у якій галузі вони перебувають, як це видно з:


26

Нарешті я знайшов спосіб зробити те, що хотів ОП. Це так просто, як:

git log --graph [branchname]

Команда відобразить усі коміти, які доступні з наданої гілки у форматі графіка. Але ви можете легко відфільтрувати всі коміти на цій гілці, переглянувши графік комітів, який *є першим символом у рядку фіксації.

Наприклад, давайте подивимось уривок git log --graph masterна cakephp GitHub repo нижче:

D:\Web Folder\cakephp>git log --graph master
*   commit 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4
|\  Merge: c3f45e8 0459a35
| | Author: José Lorenzo Rodríguez <lorenzo@users.noreply.github.com>
| | Date:   Tue Aug 30 08:01:59 2016 +0200
| |
| |     Merge pull request #9367 from cakephp/fewer-allocations
| |
| |     Do fewer allocations for simple default values.
| |
| * commit 0459a35689fec80bd8dca41e31d244a126d9e15e
| | Author: Mark Story <mark@mark-story.com>
| | Date:   Mon Aug 29 22:21:16 2016 -0400
| |
| |     The action should only be defaulted when there are no patterns
| |
| |     Only default the action name when there is no default & no pattern
| |     defined.
| |
| * commit 80c123b9dbd1c1b3301ec1270adc6c07824aeb5c
| | Author: Mark Story <mark@mark-story.com>
| | Date:   Sun Aug 28 22:35:20 2016 -0400
| |
| |     Do fewer allocations for simple default values.
| |
| |     Don't allocate arrays when we are only assigning a single array key
| |     value.
| |
* |   commit c3f45e811e4b49fe27624b57c3eb8f4721a4323b
|\ \  Merge: 10e5734 43178fd
| |/  Author: Mark Story <mark@mark-story.com>
|/|   Date:   Mon Aug 29 22:15:30 2016 -0400
| |
| |       Merge pull request #9322 from cakephp/add-email-assertions
| |
| |       Add email assertions trait
| |
| * commit 43178fd55d7ef9a42706279fa275bb783063cf34
| | Author: Jad Bitar <jadbitar@mac.com>
| | Date:   Mon Aug 29 17:43:29 2016 -0400
| |
| |     Fix `@since` in new files docblocks
| |

Як бачимо, лише виконує 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4і c3f45e811e4b49fe27624b57c3eb8f4721a4323bє *істотою першим символом у рядках. Ці комісії відбуваються з головного відділення, а інші чотири - з інших гілок.


11

Наступна команда оболонки повинна робити те, що ви хочете:

git log --all --not $(git rev-list --no-walk --exclude=refs/heads/mybranch --all)

Коваджі

Якщо ви mybranchзареєструвались, вищевказана команда не працюватиме. Це тому, що комісії на mybranchних також доступні HEAD, тому Git не вважає, що ці документи є унікальними mybranch. Щоб змусити його працювати, коли mybranchвін перевіряється, потрібно також додати виключення для HEAD:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=HEAD \
    --all)

Однак, ви не повинні виключати, HEADякщо це mybranchне перевірено, інакше ви ризикуєте показати комісії, які не є ексклюзивними mybranch.

Аналогічно, якщо у вас є віддалена гілка з назвою, origin/mybranchяка відповідає локальній mybranchгілці, вам доведеться її виключити:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=refs/remotes/origin/mybranch \
    --all)

І якщо віддалена гілка є гілкою за замовчуванням для віддаленого сховища (зазвичай це стосується лише origin/master), вам доведеться також виключити origin/HEAD:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=refs/remotes/origin/mybranch \
    --exclude=refs/remotes/origin/HEAD \
    --all)

Якщо ви перевірили гілку, і там є віддалене відділення, а віддалене відділення є за замовчуванням для віддаленого сховища, то в кінцевому підсумку виключаєте багато:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=HEAD
    --exclude=refs/remotes/origin/mybranch \
    --exclude=refs/remotes/origin/HEAD \
    --all)

Пояснення

git rev-listКоманда є командою низького рівня (водопровід) , який йде задані зміни і відвали ідентифікатори SHA1 зустрічаються. Думайте про це як еквівалент, за git logвинятком того, що він показує лише SHA1 - жодного повідомлення журналу, імені автора, відмітки часу, нічого з цього «вигадливого» матеріалу.

Цей --no-walkваріант, як випливає з назви, заважає git rev-listходити по ланцюжку родовідних. Отже, якщо ви введете git rev-list --no-walk mybranchйого, він буде надрукувати лише один ідентифікатор SHA1: ідентифікатор комітету mybranchгілки гілки.

В --exclude=refs/heads/mybranch --allаргументах кажуть , git rev-listщоб почати з кожного посилання , за винятком refs/heads/mybranch.

Отже, коли ви запускаєте git rev-list --no-walk --exclude=refs/heads/mybranch --all, Git друкує ідентифікатор SHA1 кожного комітету, за винятком, крім refs/heads/mybranch. Ці зобов’язання та їх предки - це зобов’язання, які вас не цікавлять - це ті зобов'язання, яких ви не хочете бачити.

В інших фіксацій є ті , які ви хочете бачити, тому ми збираємо висновок git rev-list --no-walk --exclude=refs/heads/mybranch --allі сказати Git , щоб показати всі , крім тих фіксацій і їх предки.

--no-walkАргумент необхідний для великих сховищ (і є оптимізацією для невеликих сховищ): Без нього, Git б друкувати, і оболонці доведеться збирати (і зберігати в пам'яті) багато більше роблять ідентифікатори , ніж це необхідно. З великим сховищем кількість зібраних комітетів може легко перевищити ліміт аргументів командного рядка оболонки.

Git bug?

Я б очікував, що це працюватиме:

git log --all --not --exclude=refs/heads/mybranch --all

але це не так. Я здогадуюсь, це помилка в Git, але, можливо, це навмисно.


Приємне пояснення. +1
VonC

5
Я прийшов сюди, бажаючи знати, як це зробити hg log -b <branch>. Я не розумію, чому люди кажуть, що git недоброзичливий. / с
weberc2

Я не знаю, чому git log --all --not --exclude=refs/heads/mybranch --allце не працює, але так git log refs/heads/mybranch --not --exclude=refs/heads/mybranch --allсамо, з тими ж застереженнями щодо виключення HEAD та походження.
Бен С

8

Швидка відповідь:

git log $(git merge-base master b2)..HEAD

Скажімо:

  1. Щоб у вас була головна галузь

  2. Зробіть кілька комітів

  3. Ви створили гілку з назвою b2

  4. Зробіть git log -n1; Id коміту - це основа злиття між b2 і master

  5. Зробіть кілька комісій у b2

  6. git log покаже вашу історію журналу b2 та master

  7. Використовуйте діапазон фіксування, якщо ви не знайомі з цією концепцією, я пропоную вам переглянути її в Google або скласти стек-переповнення,

    Для вашого фактичного контексту ви можете зробити це, наприклад

    git log commitID_FOO..comitID_BAR
    

    ".." - це оператор діапазону для команди журналу.

    Це означає, що у простій формі дайте мені всі журнали останніх, ніж на залікID_FOO ...

  8. Подивіться на точку № 4, основу злиття

    Отже: git log COMMITID_mergeBASE..HEADпокаже вам різницю

  9. Git може отримати базову злиття для вас, як це

    git merge-base b2 master
    
  10. Нарешті ви можете зробити:

    git log $(git merge-base master b2)..HEAD
    

4

Ви можете спробувати щось подібне:

#!/bin/bash

all_but()
{
    target="$(git rev-parse $1)"
    echo "$target --not"
    git for-each-ref --shell --format="ref=%(refname)" refs/heads | \
    while read entry
    do
        eval "$entry"

        test "$ref" != "$target" && echo "$ref"
    done
}

git log $(all_but $1)

Або, запозичивши рецепт у Посібнику користувача Git :

#!/bin/bash
git log $1 --not $( git show-ref --heads | cut -d' ' -f2 | grep -v "^$1" )

+1. Я писав у своїй відповіді, що вам потрібно проаналізувати зобов’язання, щоб знайти походження вашої гілки, і ви, здається, зробили саме це.
VonC

Ви використовували log --walk-reflogs? Я читаю про цей варіант і дає мені потрібні мені результати до цих пір, (все ще тестую)
dimirc

@dimirc Reflogs - це інший звір разом. Він записує точки відгалуження з часом, як правило, з метою відновлення. Я не впевнений, що ви робите на своєму гачку після отримання, але, можливо, якби ви пояснили це, люди могли б дати більш розумну відповідь на вашу проблему.
Джон Сакмайстер

Мені просто потрібно проаналізувати / перевірити всі повідомлення про фіксацію в один момент. Я хочу висвітлити те, якщо хтось натискає кілька команд на майстер і створює нову гілку з декількома комісіями. Гак після отримання повинен перевірити зміни, зроблені для обох записів / гілок, наприклад, головного та нового відгалуження, мені потрібно знати межі для нової гілки, щоб уникнути розбору повідомлень про комісію двічі, оскільки це може бути здійснено з боку ведучого.
dimirc

1
Добре. Тоді я думаю, що вищенаведений підхід, який я окреслив, справді - це те, чого ви хочете. Що стосується рефлог, записи будуть відпадати через деякий період часу, і я думаю, що це викличе у вас певні головні болі. Ви можете поглянути і на використання git show-ref --tags.
Джон Сакмайстер

4
git rev-list --exclude=master --branches --no-walk

перелічить поради кожної галузі, яка не є master.

git rev-list master --not $(git rev-list --exclude=master --branches --no-walk)

перелічить усі комісії в masterісторії Росії, яких немає в історії інших галузей.

Послідовність послідовностей є важливою для параметрів, які встановлюють фільтр-трубопровід для вибору фіксації, тому --branchesмає дотримуватися будь-яких моделей виключення, які він повинен застосовувати, і --no-walkповинен слідувати фільтрам, що постачають перелік рев-списку, який не повинен ходити.


4

Це виведе коміти на поточну гілку. Якщо передається якийсь аргумент, він просто виводить хеші.

git_show_all_commits_only_on_this_branch

#!/bin/bash
function show_help()
{
  ME=$(basename $0)
  IT=$(cat <<EOF
  
  usage: $ME {NEWER_BRANCH} {OLDER_BRANCH} {VERBOSE}
  
  Compares 2 different branches, and lists the commits found only 
  in the first branch (newest branch). 

  e.g. 
  
  $ME         -> default. compares current branch to master
  $ME B1      -> compares branch B1 to master
  $ME B1 B2   -> compares branch B1 to B2
  $ME B1 B2 V -> compares branch B1 to B2, and displays commit messages
  
  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi

# Show commit msgs if any arg passed for arg 3
if [ "$3" ]
then
  OPT="-v"
fi

# get branch names
OLDER_BRANCH=${2:-"master"}
if [ -z "$1" ]
then
  NEWER_BRANCH=$(git rev-parse --abbrev-ref HEAD)
else
  NEWER_BRANCH=$1
fi

if [ "$NEWER_BRANCH" == "$OLDER_BRANCH" ]
then
  echo "  Please supply 2 different branches to compare!"
  show_help
fi

OUT=$(\git cherry $OPT $OLDER_BRANCH $NEWER_BRANCH)

if [ -z "$OUT" ]
then
  echo "No differences found. The branches $NEWER_BRANCH and $OLDER_BRANCH are in sync."
  exit;
fi

if [ "$OPT" == "-v" ]
then
  echo "$OUT"
else
  echo "$OUT" | awk '{print $2}'
fi

1
Це створило близько 100 невідповідних для мене повідомлень журналу.
Арлі Стівенс

Привіт @ArlieStephens - я спробував це, і, здавалося, він працює для мене ще? Я щойно додав до цього довідку та більше повідомлень про помилки. Дайте мені знати, як це йде!
Бред Паркс

Цікаво. Дивлячись на код, як у вас його зараз, я думаю, він може бути таким же простим, як оригінал, якщо припустити, що гілка, про яку я дбаю, вийшла з майстра. За допомогою поточного коду я міг би чітко вказати батьківську гілку. (IIRC, гілка мого розробника походить із відділення випуску, а не майстра.)
Арлі Стівенс

@ArlieStephens - так, я не думаю, що я змінив будь-яку функціональність .... я оновив її ще раз і зробив документи трохи точнішими після деяких локальних тестувань ... і додав "багатослівний" варіант, який був там раніше, але я цього не зробив
Бред Паркс

3

Я використовую такі команди:

git shortlog --no-merges --graph --abbrev-commit master..<mybranch>

або

git log --no-merges --graph --oneline --decorate master..<mybranch>

1

Я знайшов такий підхід відносно легким.

Оформити замовлення на філію та далі

  1. Біжи

    git rev-list --simplify-by-decoration -2 HEAD
    

Це забезпечить лише два SHA:

1) останній комітет філії [C1]

2) і зобов’язати батьків до першого комітету гілки [C2]

  1. Тепер біжи

    git log --decorate --pretty=oneline --reverse --name-status <C2>..<C1>
    

Тут C1 і C2 - два рядки, які ви отримаєте при виконанні першої команди. Поставте ці значення без <> у другу команду.

Це дасть список історії зміни файлів у гілці.


Якщо ви прочитаєте перші три рядки запитання, ви побачите, що автор перераховує цю точну команду і пояснює, чому це не те, що вони шукають
black_fm

Ах @black_fm Я змінив відповідь. Ви можете проголосувати за нього, якщо зараз вам це стане в нагоді. :)
Mustkeem K

0

У моїй ситуації ми використовуємо Git Flow та GitHub. Все, що вам потрібно зробити, це: порівняти свою функціональну гілку з вашою розробкою на GitHub.

На ньому будуть показані зобов’язання, зроблені лише для вашої галузі функцій.

Наприклад:

https://github.com/your_repo/compare/develop...feature_branch_name


Я погоджуюсь, що коли ви потрапляєте в ситуацію "Я хочу побачити, як виглядатиме запит на виклик", найкращим рішенням є часто ігнорувати, gitа замість цього використовувати GitHub просто зробити запит на потяг або порівняти гілки.
пкамб
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.