Як "git show" зробити об'єкт злиття з комбінованим різницевим виведенням, навіть коли кожен змінений файл узгоджується з одним із батьків?


186

Зробивши «просте» злиття (одне без конфліктів), git showзазвичай показує лише щось на зразок

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

Це відбувається тому, що для злиття git showвикористовується комбінований формат diff, який опускає файли, що узгоджуються з будь-якою з батьківських версій.

Чи є спосіб змусити git все-таки показувати всі відмінності в комбінованому режимі різниці?

Додавання git show -mпокаже відмінності (використання парних відмінностей між новою та всіма батьківськими версіями відповідно), але я вважаю за краще, щоб різниці, позначені +/-, у відповідних стовпцях, як у комбінованому режимі.


1
@ Tilman Vogel: будь ласка, перегляньте прийняту відповідь - Схоже, є кращі відповіді
Jayan

1
@Jayan Хоча інші відповіді користуються більшою популярністю, оскільки містять корисні підказки, вони насправді не наближаються до моєї проблеми, тому що робити просто двосторонні розбіжності. Я шукав тристоронню різницю.
Tilman Vogel

Відповіді:


-3

Ні, немає ніякого способу зробити це git show. Але це, звичайно, було б приємно іноді, і, ймовірно, це буде відносно легко реалізувати у вихідному коді git (адже, вам просто потрібно сказати це, щоб не обрізати те, що, на його думку, є стороннім виведенням), тому патч робити це ймовірно, вони приймуть підтримку git.

Однак будьте уважні, чого ви хочете; об'єднання гілки з однорядковою зміною, яку було роздвоєно три місяці тому, все ще матиме величезну різницю порівняно з основною лінією, і тому така повна різниця була б майже повністю не корисною. Ось чому git не показує цього.


12
Будь ласка, не кажіть "ніякого способу зробити це" так чітко, як це можливо - дивіться інші відповіді. Це дуже оманливо сказати.
kgadek

1
git show HEAD ^ ... HEAD; Рішення # per @ hesham_EE
Майкл

git show HEAD ~ 1 ... HEAD ~ 0 - тільки ім'я; # кращий синтаксис. Для ітерації pr.
Майкл

256

Подивіться на повідомлення про здійснення:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

помітити рядок:

Merge: fc17405 ee2de56

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

git diff ee2de56..fc17405

показати лише імена змінених файлів:

git diff --name-only ee2de56..fc17405

і щоб витягнути їх, ви можете додати це до своєї gitconfig:

exportfiles = !sh -c 'git diff $0 --name-only | "while read files; do mkdir -p \"$1/$(dirname $files)\"; cp -vf $files $1/$(dirname $files); done"'

потім використовуйте його, роблячи:

git exportfiles ee2de56..fc17405 /c/temp/myproject

Дякую за пропозицію, але, думаю, це не вирішує мою проблему. Через обмежену розмітку коментарів та форматування я додав свій коментар до вашої відповіді. Вибачте за це! Потрібно пройти рецензування до моменту появи.
Тільман Фогель

6
Здається, моя редакція відхилена. Підсумовуючи: у вашій різниці не вказано, які доповнення походять із якої галузі. І ви не можете розрізнити, чи були додані зміни у другій чи видалені у першій гілці.
Tilman Vogel

45
Краще рішення git diff fc17405...ee2de56- це покаже всі зміни на ee2de56, які можна отримати з комісій на fc17405, і я вважаю, що ви хочете. Зверніть увагу на 3 крапки замість двох.
Kris Nuttycombe

1
@KrisNuttycombe 3 крапки і порядок. І ваш коментар - це те, що я шукав, що, на мою думку, більше схоже на те, що хотіла ОП.
Ізката

@KrisNuttycombe Це якось не працює git log, що все ще показує всі коміти, як і ..варіант. ..і ...зробіть те ж саме log, але diffвони різні! Як отримати список комітетів, об'єднаних у цю галузь?
Rudie

77

Краще рішення (згадується @KrisNuttycombe):

git diff fc17405...ee2de56

для комісії злиття:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

щоб показати всі зміни, до ee2de56яких можна дістатися з комісій fc17405. Зверніть увагу на порядок хешів фіксації - він такий самий, як показано в інформації про злиття:Merge: fc17405 ee2de56

Також зверніть увагу на 3 крапки ...замість двох !

Для списку змінених файлів ви можете використовувати:

git diff fc17405...ee2de56 --name-only

Це саме те, що я був після +1.
geedoubleya

Це фактично показує результат конфлікту злиття, тоді як інша відповідь не відповідає.
Под

12

Ви можете створити гілку з HEAD, встановленим на один комітет перед об'єднанням. Потім ви можете:

git merge --squash testing

Це буде зливатися, але не виконувати. Тоді:

git diff

5

Здається, тут відповіли: https://public-inbox.org/git/7vd392ezhx.fsf@alter.siamese.dyndns.org/

Тож аналогічно, біг

$ git diff --cc $ M $ M ^ 1 $ M ^ 2 $ (git merge-base $ M ^ 1 $ M ^ 2)

Потрібно показати комбінований патч, який пояснює стан у $ M щодо станів, записаних у його батьків та бази злиття.


чи знаєте ви, чи будь-який інструмент може бути налаштований для відображення такої різниці вбік, потенційно в декількох стовпцях (як, наприклад, у вікні вирішення конфлікту IntelliJ злиття)? Вашу відповідь саме я шукав
Макс

@Max Ні, боюсь, я цього не роблю. Гуглінг "n-way visual diff" дає деякі посилання, тому я спробував їх.
max630

4

Я думаю, що вам просто потрібно «git show -c $ ref». Спробуючи це у сховищі git на a8e4a59, видно комбінований розріз (плюс / мінус символи в одному з 2 стовпців). Як згадується посібник з git-show, він в значній мірі делегує "git diff-tree", тому ці варіанти виглядають корисними.


3
Ні, для "простого" злиття git show -c $refпоказується такий же вихід, як я цитував, тобто різниці немає. -cвибирає комбінований режим диференціалів, дуже подібний до режиму за замовчуванням для об'єднань, який є "--cc", див. git help showта git help diff-tree. Обидва повністю опускають файли, які погоджуються з будь-якою з батьківських версій цього файлу.
Тільман Фогель

a8e4a59насправді не підпадає під категорію злиття комітетів, я маю на увазі. Ця комісія злиття дійсно містить один файл, який відрізняється від обох батьківських версій. Documentation/git-fast-import.txtдеякі речі додаються від одного з батьків, а деякі - від іншого. Це призводить до не порожнього виходу з git diff-tree --cc. Однак показані лише зміни в цій "конфліктній" справі. Всі "чисті" результати злиття, дивіться git show -m a8e4a59, зовсім не показані.
Тільман Фогель

1
@TilmanVogel: Дякую за те, що вказали, що "нецікаві" злиття файлів залишаються поза git show -cвихідними. ( man git-diff-treeВтім, "Крім того, у ньому перераховані лише файли, які були змінені від усіх батьків", але я, безумовно, цього не помітив.)
Пол Уіттакер

3

у вашому випадку вам просто потрібно

git diff HEAD^ HEAD^2

або просто хеш для вас:

git diff 0e1329e55^ 0e1329e55^2

4
Ні, це просто просте двостороннє розходження між двома батьками. Те , що я просив був режим , який одночасно показує відмінностей між git merge-base HEAD^ HEAD^2і HEAD^і HEAD^2в тому ж стилі , як це робиться для файлів , які були злиті з конфліктами.
Тільман Фогель

3

Якщо ваш об'єкт злиття виконує 0e1329e5, як зазначено вище, ви можете отримати різницю, яка містилася в цьому злитті, виконавши:

git diff 0e1329e5^..0e1329e5

Я сподіваюся, що це допомагає!


3

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

git diff HEAD~1..HEAD

Якщо ви не є об'єктом злиття, просто замініть HEAD на об'єднання. Цей метод здається найпростішим та інтуїтивно зрозумілим.


1
Це не "комбінований різний" вихід. Отримати різницю між кожною парою батьків та HEAD тут не є проблемою.
Тільман Фогель

2

Ви можете використовувати команду diff-дерева зі прапорцем -c. Ця команда показує, які файли були змінені під час об'єднання.

git diff-tree -c {merged_commit_sha}

Я отримав опис прапора -c від Git-Scm :

Цей прапор змінює спосіб відображення комірки злиття (що означає, що він корисний лише тоді, коли команді задано одну, або --stdin). Він показує відмінності кожного з батьків до результату злиття одночасно, замість того, щоб показувати попарно відмінності між батьківським і результатом один за одним (що і робить варіант -m). Крім того, у ньому перелічені лише файли, які були змінені від усіх батьків.


2
Здається, гарна стаття на цю тему: haacked.com/archive/2014/02/21/reviewing-merge-commissions, а може, і це: longair.net/blog/2009/04/16/git-fetch-and-merge
Девін Г Род

1

Я побудував загальний підхід до виконання різних операцій на об'єднанні.

Крок перший : Додайте псевдонім до git, редагуючи ~/.gitconfig:

[alias]
  range = "!. ~/.githelpers && run_on_merge_range"

Крок другий : В ~/.githelpers, визначте функцію bash:

run_on_merge_range() {
  cmd=$1; shift
  commit=$1; shift
  range=$(git show $commit | grep Merge: | awk '{print $2 "..." $3}')
  echo "git $cmd $range $@"
  if [ -z $range ]; then
    echo "No merge detected"
    exit 1
  fi
  git $cmd $range $@
}

Крок третій : прибуток!

git range log <merge SHA> --oneline
git range diff <merge SHA> --reverse -p
git range diff <merge SHA> --name-only

Тут, мабуть, багато місця для вдосконалення, я просто збила це разом, щоб пройти роздратовану ситуацію. Не соромтеся глузувати з мого синтаксису та / або логіки.


Зверніть увагу , що ви можете змінити «...» на «..» в "AWK" біт, в залежності від того, що вам потрібно і яку команду ви працюєте: stackoverflow.com/questions/462974 / ...
Nerdmaster
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.