Git Дивергентное переименование - PullRequest
13 голосов
/ 13 января 2011

Я хотел бы знать, как вы справляетесь с такой ситуацией в Git:

  • создать ветку task001 от мастера
  • master: измените foo.c и переименуйте его в bar.c
  • task001: измените foo.c и переименуйте его в moo.c
  • объединить task001 с master

Что Git говорит мне:

CONFLICT (rename/rename): Rename "foo.c"->"bar.c" in branch "HEAD" rename "foo.c"->"moo.c" in "task001"
Automatic merge failed; fix conflicts and then commit the result.

Как мне это решить? Я имею в виду, что я все еще хочу объединить два файла после разрешения конфликта имен.

Спасибо.

Ответы [ 2 ]

13 голосов
/ 13 января 2011

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

1. Просто разрешение конфликта, так что у вас есть только разошедшиеся moo.c и bar.c

Здесь я предполагаю, что вы хотите получить bar.c и moo.c с их изменениями из каждой ветви в объединенной версии. Я бы справился с этим путем разрешения конфликта в индексе и фиксации. Описанная вами ситуация выглядит следующим образом:

$ git log --pretty=oneline --graph --decorate master task001
* fce127471ab5d1ef55b1d16412a75a7129782517 (task001) Rename to a different file on task001
* 8edbc1357a3c0484dc077f6f7ce43de91d21e794 A small change on the task001 branch
| * d10e9020d147a4bbd3688744823380322bf37718 (HEAD, master) Rename on master to bar.c
| * f952617645456a551df07f219bfdc95e00c8ac9b Added a small change in master
|/  
* e8602eef46af744defd4fb4073ecdb6a7afbfd28 Initial version of foo.c

Если я затем сливаю task001 в master, он выдаст ту же ошибку, что и вы:

$ git merge task001 
CONFLICT (rename/rename): Rename "foo.c"->"bar.c" in branch "HEAD" rename "foo.c"->"moo.c" in "task001"
Automatic merge failed; fix conflicts and then commit the result.

Тогда git status покажет вам краткое изложение проблем:

$ git status
# On branch master
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   added by us:        bar.c
#   both deleted:       foo.c
#   added by them:      moo.c
#
no changes added to commit (use "git add" and/or "git commit -a")

Теперь вам просто нужно использовать git add и git rm для разрешения конфликтов:

$ git add bar.c
$ git rm --cached foo.c
foo.c: needs merge
moo.c: needs merge
rm 'foo.c'
$ git add moo.c
$ git status
# On branch master
# Changes to be committed:
#
#   new file:   moo.c
#

(я использовал --cached для удаления foo.c, потому что его больше нет в рабочей копии, а --cached означает, что команда просматривает только индекс - в противном случае вы получите сообщение о том, что foo.c не существует.)

Тогда вы просто фиксируете результаты:

$ git commit
[ save the prepopulated commit message ]

И вы разрешили конфликты, и в объединенной версии есть bar.c и moo.c.

(мимоходом отмечаю, что git merge -s resolve работает для меня в простейшем примере ситуации, описанном здесь, но я надеюсь, что это более полезно.)

2. Объединение bar.c и moo.c обратно в один файл

Из ваших комментариев ниже видно, что на самом деле вы хотели бы снова объединить эти файлы в один, слияния изменений в файле в обеих ветвях. Если вы хотите, чтобы стратегии слияния git помогли вам в этом, файлы в каждой ветке должны иметь одинаковый путь перед слиянием, поэтому вам нужно переименовать хотя бы одну из них перед слиянием. Предположим, вы хотите, чтобы объединенный файл назывался quux.c, хотя вы, конечно же, могли бы сделать его снова foo.c. Затем вы можете выполнить следующие шаги, которые переименуют файл в каждой ветви перед слиянием:

# Rename the file on master:

$ git checkout master
Already on 'master'
$ git mv bar.c quux.c
$ git commit -m "Rename bar.c to quux.c on branch master"
[master f9b3f49] Rename bar.c to quux.c on branch master
 1 files changed, 0 insertions(+), 0 deletions(-)
 rename bar.c => quux.c (100%)

# Rename the file on task001:

$ git checkout task001 
Switched to branch 'task001'
$ git mv moo.c quux.c
$ git commit -m "Rename moo.c to quux.c as well on branch task001"
[task001 c71ad89] Rename moo.c to quux.c as well on branch task001
 1 files changed, 0 insertions(+), 0 deletions(-)
 rename moo.c => quux.c (100%)

# Switch back to master, and merge in task001:

$ git checkout master
Switched to branch 'master'
$ git merge task001

Если изменения не вступали в конфликт, то в этот момент это слияние должно просто работать. В примере, который я пробовал, они конфликтовали, поэтому мне нужно было отредактировать файл, git add файл и зафиксировать результат:

Renaming foo.c->quux.c
Auto-merging quux.c
CONFLICT (content): merge conflict in quux.c
Automatic merge failed; fix conflicts and then commit the result.
$ emacs -nw quux.c 
$ git add quux.c
$ git commit
[master 8baa7cb] Merge branch 'task001'
$ ls
quux.c
0 голосов
/ 13 января 2011

Простой способ исправить это Сначала прервать текущее слияние

git merge --abort

Теперь решите, какую версию файла вы хотите использовать, и используйте стратегию слияния (с флагом -s)

Вы на ветке мастера.Если вы хотите сохранить имя, которое вы задали в master, используйте эту команду

git merge -s ours task

Если вы хотите использовать версию из задачи

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