Можно ли исключить определенные коммиты при слиянии git?

Допустим, я хочу выполнить слияние из ветки выпуска в ветку 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

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

Возможный дубликат git - пропуск определенных коммитов при слиянии - знаю, что моложе, но его принятый ответ ИМХО лучше

Tobias Kienzler 11.08.2017 11:53
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
73
1
59 751
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

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

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

Но что произойдет, если вы снова попытаетесь объединить эту ветку?

Evgeny 22.09.2010 10:18

Какими точными командами это нужно сделать? Я не вижу способа "отбросить" нежелательные коммиты

Henning 08.06.2011 15:37

@Henning, когда вы git rebase -i other-branch, он дает вам текстовый редактор с кучей коммитов в нем. Удалите ненужные строки.

Dustin 09.06.2011 04:14

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

Я нашел решение, которое мне подходит в книге Pro Git.

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

На ветке А:

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

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

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

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

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

charliepark 13.05.2011 16:08

У меня это почему-то не работает. Я создал новую ветку с фиксацией, изменяющей файл, и добавил файл .gitattributes в обе ветки. Когда я снова сливаюсь с исходной веткой, кажется, что она полностью игнорирует строку в .gitattributes и в любом случае извлекает измененный файл. Есть какие-то настройки, которые мне не хватает?

robbles 01.10.2012 03:59

У меня не работает. Я тоже выполнил инструкции в вопросе, указанном VonC. Я на винде. Файл, который я пытаюсь избежать слияния, представляет собой точечный файл (.core.config). Мне нужно заключить это имя в кавычки или что-то в этом роде?

Sean 09.05.2013 01:27

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

Caumons 28.09.2013 19:57

@robbles Каумонс прав. По сути, этот атрибут срабатывает только в случае конфликта слияния. В вашем случае у вас есть слияние FF. Git просто делает это без проверки стратегии слияния

Johnny Z 09.06.2015 23:23

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

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

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

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

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

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

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

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

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

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

Множественные коммиты слияния

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

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

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

      -------------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'

Любой пример автоматизации множественных коммитов слияния?

Santos 21.12.2016 20:07

Решение, которое дает одну фиксацию слияния с использованием Cherry Pick, просто фантастическое! Спасибо! Это именно то, что мне было нужно. У нас есть два проекта, разветвленных из одного источника. Нам нужно сохранить несколько различий между ними, но в целом нам нужно, чтобы большая часть изменений была объединена взад и вперед. Отличный пост!

Brent K. 20.03.2020 23:57

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

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

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

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

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

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

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

Ron Wertlen 01.07.2016 16:44

@RonWertlen Вы правы в утверждении, что мастер не может быть снова объединен с этой «рабочей веткой» / веткой выпуска без введения эффекта возврата. - Но это верно не только для предложенной мной стратегии 3 моего ответа, но и для стратегии 1. - Это также одна из причин, по которой я лично не буду следовать рабочему процессу из вопроса ОП.

Robert Siemer 01.07.2016 16:56

Я тоже с тобой согласен. 1 и 2 - это антирабочие процессы. Если у вас есть долгоживущие ветки и вы хотите постоянно сохранять коммиты вне одной и другой, пора подумать о реструктуризации вашего проекта и использовании подмодулей (с node.js у вас также есть node_modules в качестве параллельный механизм для достижения того же самого).

Ron Wertlen 06.07.2016 15:29

Кроме того, № 2. не выражается в графике истории, это утверждение не на 100% ясно. Практически можно «солгать» себе историю, сбросив или переустановив и переписав индекс удаленного репо с помощью «--force». Это, конечно, очень плохая идея.

Ron Wertlen 06.07.2016 15:31

@RonWertlen Вы только что напомнили мне способ что-то объединить, но пропустив некоторые коммиты. - Но это никак не связано с пультами.

Robert Siemer 07.07.2016 14:52

Другие вопросы по теме