git merge: удаление файлов, которые я хочу сохранить! - PullRequest
49 голосов
/ 11 сентября 2009

Как можно объединить две ветви в git, сохранив необходимых файлов из ветви?

При объединении двух ветвей, если файл был удален в одной ветви, а не в другой, файл в конечном итоге удаляется.

Например:

  • При создании новой ветки в мастере существует файл
  • вы удаляете файл из мастера, так как он нам не нужен (пока)
  • вы вносите изменения в ветку, чтобы добавить функцию, которая опирается на существующий файл
  • вы исправляете ошибки в мастере (не может быть отброшено)
  • когда-нибудь вы объединитесь, и файл исчезнет!

Как воспроизвести:

  1. Создание git-репо с одним файлом.

    git init
    echo "test" > test.txt
    git add .
    git commit -m "initial commit"
    
  2. Создать ветку

    git branch branchA
    
  3. Удалить файл в мастере

    git rm test.txt
    git commit -m "removed file from master"
    
  4. Произведите ЛЮБЫЕ изменения в ветке A, которые не касаются удаленного файла (его необходимо изменить, чтобы избежать конфликта)

    git checkout branchA
    touch something.txt
    git add .
    git commit -m "some branch changes"
    

Отсюда, при любом слиянии этих двух веток, файл test.txt удаляется. Предполагая, что мы полагаемся на файл для branchA, это большая проблема.


Неудачные примеры:

Слияние 1

git checkout branchA
git merge master
ls test.txt

Слияние 2

git checkout master
git merge branchA
ls test.txt

Ребаз 1

git checkout branchA
git rebase master
ls test.txt

Ответы [ 5 ]

27 голосов
/ 11 сентября 2009

Это интересный вопрос. Поскольку вы удалили файл после того, как BranchA был создан, а затем сливаете master в BranchA, я не уверен, как Git сможет понять, что существует конфликт.

После неудачного слияния вы можете отменить, а затем снова слить, но добавить обратно файл:

git checkout HEAD@{1} .
git merge --no-commit master
git checkout master test.txt
git add test.txt
git commit
6 голосов
/ 11 сентября 2009

Для быстрого исправления в этом случае, "git revert" коммит, который удалил файл.

Когда эта ситуация возникнет в будущем, лучший способ справиться с ней - убедиться, что создание нового файла происходит в ветви. Затем он добавляется на мастер при слиянии, но у вас пока нет файла, лежащего в мастере.

4 голосов
/ 06 ноября 2012

Пример Кейси не работал для моего случая - я не смог оформить test.txt из master, потому что его больше не было в этой ветви:

$ git checkout master test.txt
error: pathspec 'test.txt' did not match any file(s) known to git.

К счастью, я мог вытащить файл из собственного branchA HEAD:

$ git checkout branchA
$ git merge --no-commit master
$ git checkout HEAD test.txt
$ git add test.txt
$ git commit
2 голосов
/ 11 сентября 2009

Вам нужно изменить файл в ветке, чтобы произошел конфликт слияния с удалением в транке.

То же самое произойдет, если вы, например, удалите объявление для чего-либо в заголовочном файле в транке (потому что это никому не нужно) и добавите зависимость от этого объявления к некоторым файлам без заголовка в филиал. Когда вы объединяетесь, так как ветвь не касается (этой части) заголовка, она просто удалит объявление, и все сломается.

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

1 голос
/ 21 февраля 2016

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

Моя история пошла примерно так. Имена ветвей были изменены, чтобы защитить невинных.

  1. создание и фиксация файлов для новой функции в мастере
  2. понимаем, что это дополнение будет более сложным, чем планировалось изначально, поэтому оно перешло на feature_branch
  3. Удалены файлы из мастера, чтобы не нарушать нормальный рабочий процесс с RB и т. Д.
  4. Время проходит, больше коммитов на master, ни одного на feature_branch
  5. Возобновить работу над функцией, git merge master на feature_branch приводит к удалению исходных файлов (конечно), git reset --hard до слияния
  6. Применяется решение, описанное выше
...