GIT: как заставить коммит слиться с предком - PullRequest
13 голосов
/ 24 июля 2011

В GIT у меня есть две ветви и два коммита:

 A(master)---B(branch "topic")
  • ГОЛОВКА ветки 'master' - коммит A
  • ГОЛОВКА ветки 'topic' - коммит B
  • коммит A является родителем коммита B

Я хотел бы создать коммит слияния C в ветке "topic" (родительские объекты A и B). (Я знаю, что это кажется странным, и что коммит слияния будет пустым.)

 A(master)---B---C (branch "topic")
  \-------------/

Мне удалось создать этот коммит слияния слишком сложным способом (см. Ниже). Есть ли более простой способ создать этот коммит слияния?

Спасибо за ваши ответы!


Исходное состояние:

$ git init plop
Initialized empty Git repository in /tmp/plop/.git/
$ cd plop/
$ git commit -m "Initial commit (commit A)"  --allow-empty
[master (root-commit) a687d4e] Initial commit (commit A)
$ git checkout -b topic
Switched to a new branch 'topic'
$ git commit -m "Some work on my topic branch (commit B)" --allow-empty
[topic d4d1c71] Some work on my topic branch (commit B)
$ #OK, we now reached the initial state

Некоторые попытки:

$ git merge master #Does not work
Already up-to-date.
$ git merge --no-ff -s ours master #Does not work
Already up-to-date.

Есть ли более простой способ добиться следующего?

$ #Let's try another way (too complex!)
$ git checkout master
Switched to branch 'master'
$ git merge --no-ff topic
Already up-to-date!
Merge made by recursive.
$ git checkout topic
Switched to branch 'topic'
$ git merge master
Updating d4d1c71..641e7ae
Fast-forward
$ git checkout master
Switched to branch 'master'
$ git reset --hard HEAD^1
HEAD is now at a687d4e Initial commit
$ git checkout topic
Switched to branch 'topic'
$ git log #This is what I wanted to reach
commit 641e7aeb614d9b49796e8f11abd3a0290ac08b40
Merge: a687d4e d4d1c71
Author: xxx <yyy.zzz>
Date:   Sat Jul 23 12:52:41 2011 +0200

    Merge branch 'topic'

commit d4d1c71c87b94335c8852ab7675cbb663965ef7d
Author: xxx <yyy.zzz>
Date:   Sat Jul 23 12:50:11 2011 +0200

    Some work on my topic branch (commit B)

commit a687d4eb88b9f6d661122a5766dd632dd462fbaa
Author: xxx <yyy.zzz>
Date:   Sat Jul 23 12:49:52 2011 +0200

    Initial commit (commit A)

Ответы [ 5 ]

9 голосов
/ 24 июля 2011

UPD : более чистый способ сделать то же самое, не связываясь напрямую с sha1:

$ echo "merge commit" | git commit-tree topic^{tree} -p master -p topic
4201b6abae6bb06f929ea00fbc35019679d55535

$ git merge 4201b6abae6bb06f929ea00fbc35019679d55535
Updating b826a8e..4201b6a
Fast-forward

Или даже однострочная команда:

$ git merge $(echo "merge commit" | git commit-tree topic^{tree} -p master -p topic)

Для получения подробной информации о том, что это делает - прочитайте весь ответ:)


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

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

$ git log --format=oneline -2
b826a8e93ac8da0de5bfb5b70d5f4e7c352a01fa change from topic
8b7653a529fb3ce964fda79bfd57e645441ad893 change from master

Тогда вы должны знать sha1 конкретного объекта дерева коммита B:

$ git cat-file -p topic
tree 867f31c455a371756ec353b54d755f51d98d62c4
parent 8b7653a529fb3ce964fda79bfd57e645441ad893
author ivan-danilov <email@gmail.com> 1311518908 +0300
committer ivan-danilov <email@gmail.com> 1311518908 +0300

change from topic

Так что это 867f31c455a371756ec353b54d755f51d98d62c4. И, наконец, вы должны выполнить команду git-commit-tree:

$ echo "merge commit" | git commit-tree 867f31c455a371756ec353b54d755f51d98d62c4 -p b826a8e93ac8da0de5bfb5b70d5f4e7c352a01fa -p 8b7653a529fb3ce964fda79bfd57e645441ad893
4201b6abae6bb06f929ea00fbc35019679d55535

Обратите внимание, что я использовал перенаправление конвейера, так как git-commit-tree получает комментарий из потока stdin. Первый параметр - это sha1 дерева, который мы получили с git cat-file, а два других - это sha1 коммита, который мы получили с git log.

Вывод команды - это sha1 вновь созданного коммита слияния. Теперь вы хотите быстро перейти к следующей ветке темы:

$ git merge 4201b6abae6bb06f929ea00fbc35019679d55535
Updating b826a8e..4201b6a
Fast-forward

Вот и все. Вы получили то, что хотели.

2 голосов
/ 21 мая 2012

Слияние наоборот должно работать:

git branch tmp master    # tmp points to A
git checkout tmp
git merge --no-ff -m 'odd merge' topic    # merge B+A ==> C
git checkout topic
git reset --hard tmp     # topic now points to C
git branch -d tmp
2 голосов
/ 24 июля 2011

Имеет смысл сделать коммит слияния, если есть разница между master и topic - если они разошлись.В вашем случае объединять нечего - у topic уже есть все коммиты master, поэтому git не позволит вам создать слияние, которое ничего не делает.

Работает нормально, если у вас естькоммит в master, которого нет в topic:

$ git init plop
Initialized empty Git repository in C:/Temp/plop/.git/
$ cd plop
$ git commit -m "Initial commit (commit A)" --allow-empty
[master (root-commit) b6e2e91] Initial commit (commit A)
$ git commit -m "master-only commit (commit C)" --allow-empty
[master 67b491e] master-only commit (commit C)
$ git checkout HEAD~ -b topic
Switched to a new branch 'topic'
$ git commit -m "Some work on my topic branch (commit B)" --allow-empty
[topic 2251f13] Some work on my topic branch (commit B)
$ git merge master
Already up-to-date!
Merge made by recursive.

В результате ...

*   592ad46 Merge branch 'master' into topic
|\
| * 67b491e master-only commit (commit C)
* | 2251f13 Some work on my topic branch (commit B)
|/
* b6e2e91 Initial commit (commit A)
0 голосов
/ 07 апреля 2018

Официального решения этой проблемы нет, есть обходной путь. Проверьте фиксацию, в которой включен master, так что вы находитесь в состоянии detached HEAD . Затем совершить пустой коммит. Затем проверьте вашу ветку topic и объединитесь с этим пустым коммитом.

$ git checkout 9123456 # (the latest commit on master)
Note: checking out '9123456'.
You are in 'detached HEAD' state...
$ git commit --allow-empty -m 'empty commit'
[detached HEAD 9123457] empty commit
$ git checkout topic
Warning: you are leaving 1 commit behind ... 9123457 empty commit
Switched to branch 'topic'
$ git merge 9123457
0 голосов
/ 24 июля 2011

В данный момент вы находитесь в ветке темы, и поскольку она является прямым потомком мастера, объединение с мастером не имеет смысла, так как тема содержит все изменения, которые имеет мастер.Тем не менее, мастер не имеет ни одного из изменений раздела.

Если вы извлекаете мастер и затем объединяете тему в мастер, мастер должен выполнить ускоренную перемотку вперед и обновить свой заголовок.

...