Можно ли исключить определенные коммиты при выполнении git merge? - PullRequest
65 голосов
/ 02 декабря 2008

Допустим, я хочу объединить ветку релиза с веткой master, и в ветке релиза есть некоторые коммиты, которые я не хочу включать в ветку master. Есть ли способ сделать слияние, чтобы один или несколько из этих коммитов не были объединены?

Моя стратегия до сих пор заключается в следующем (в мастер):

git merge --no-commit release-branch
# Resolve conflicts and apply reverse patch of the commits that I don't want included
git commit # Edit commit message so that it lists the commits that have been reverse-patched

Есть ли лучший способ сделать это?

Ответы [ 7 ]

105 голосов
/ 19 октября 2010

Я нашел решение, которое работает для меня в Pro Git book .

Допустим, вы хотите исключить файл config.php.

На ветке А:

  1. Создайте файл с именем .gitattributes в том же каталоге с этой строкой: config.php merge=ours. Это говорит git, какую стратегию использовать при объединении файла. При этом всегда сохраняйте свою версию, т.е. версия ветки, в которую вы объединяетесь.

  2. Добавить файл .gitattributes и зафиксировать

На ветке B: повторите шаги 1-2

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

43 голосов
/ 02 декабря 2008

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

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

15 голосов
/ 30 апреля 2014

Если у вас есть ветка поддержки, где вы исправляете ошибки и создаете новые версии. На master у вас есть следующая версия, где вы также часто создаете новые версии.

Каждый раз, когда вы создаете новую версию, вы изменяете версию в каком-либо файле, фиксируете этот новый файл, создаете тег и нажимаете. Теперь слияния от support до master всегда будут конфликтовать в файле, содержащем информацию о версии.

Если файл, содержащий информацию о версии только , содержит информацию о версии, вы можете пойти с ответом fcurella. Но если он действительно может также содержать объединяемую информацию (pom.xml, gradle.properties, MANIFEST.MF, ...), вы должны выполнить некоторые дополнительные действия.

Позволяет использовать следующий пример

      C---D*---E---F* support
     /
A---B---G---H*---I master

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

Чтобы объединить с поддержкой в master без конфликтов слияния из-за сборок версий, вы можете выполнить одно из следующих действий:

Несколько коммитов слияния

git checkout master
git merge C
git merge D -s ours
git merge E
git merge F -s ours

С аргументом -s ours мы говорим git записывать только слияние без изменения рабочей области. сопоставимо с параметром --record-only svn .

Приведенное выше приведёт к следующему макету

      -------------C---D*---E---F* support
     /              \   \    \   \
A---B---G---H*---I---J---K----L---M master

Один коммит слияния с использованием cherry-pick

git checkout master
git merge support -s ours --no-commit
git cherry-pick C E --no-commit
git commit -m 'merged support into master'

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

Приведенное выше приведёт к следующему макету

      C---D*---E---F* support
     /              \
A---B---G---H*---I---J master

Можно даже автоматизировать сбор вишни.

git checkout master
git merge support -s ours --no-commit
for id in `git log support --reverse --not HEAD --format="%H [%an] %s" |
  grep -v "bump version" |
  sed "s/\(\w*\)\s.*/\1/g"`
do
  git cherry-pick --no-commit $id
done
git commit -m 'merged support into master'
4 голосов
/ 09 декабря 2008

Причина, по которой это невозможно сделать напрямую, заключается в том, что каждый коммит содержит ссылки на родительские коммиты (обычно только один, но несколько для слияний). Таким образом, если у вас есть один коммит (по сумме SHA1), вся история также фиксируется, поскольку родители также содержат ссылки на своих родителей и так далее. Таким образом, единственный способ оставить патчи в истории - это написать новый. git rebase -i во вновь созданной ветви, вероятно, самый простой способ добиться этого.

2 голосов
/ 26 июня 2015

Основной вопрос: как вы хотите представить коммиты, которые вы хотите пропустить?

  1. хитро спрятать их (не мой любимый)
  2. явно пропустить их
  3. явно отменить их

К сожалению, нет. 2 невозможно выразить в графе истории.

Нет. 1 возможно, но я бы никогда не сделал бы это: коммит слияния может содержать изменения. - Обычно коммит слияния указывает на результат слияния еще двух ветвей: все элементы, разработанные в этих ветках, должны быть в коде после слияния (т.е. в коде, указанном коммитом слияния). И больше ничего не должно быть в этом коммите.

Но удивительно, удивительно, вы можете изменить всю кодовую базу и представить ее как объединение. Эффект слияния является двойным: он объединяет дерево истории и , он должен объединять две базы кода. Первый он делает наверняка (в противном случае никто не называет это слиянием), для второго он может потерпеть неудачу, например когда возник конфликт слияния, и он был разрешен неправильно (тогда базы кода не были слиты должным образом).

Некоторые другие ответы предполагают это сокрытие. Я рекомендую явный способ: объединить и отменить коммиты.

2 голосов
/ 18 января 2012

Также возможно изменить файл .git / info / attribute и сохранить его в папке .git вместо того, чтобы добавлять файлы .gitattribute повсюду, что в конечном итоге потребует их добавления в систему контроля версий.

1 голос
/ 26 августа 2011

Если вы хотите исключить только некоторые коммиты, которые находятся в конце, вы можете просто зафиксировать определенный номер коммита:

git checkout partlyMergedFrom
git whatchanged
--> find the commit hash up to where you want to merge
git checkout partlyMergedInto
git merge e40a0e384f58409fe3c864c655a8d252b6422bfc
git whatchanged
--> check that you really got all the changes you want to have
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...