it-swarm.com.ru

git - пропускает определенные коммиты при слиянии

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

У меня есть две ветви, называемые, скажем, master10 (для v1) и master20 (для v2). Я делал исправления ошибок в v1 на ветке master10 и разрабатывал новые вещи для master20. Всякий раз, когда я исправляю ошибку, я объединяю ее с версией v2, проверяя master20 и выполняя git merge master10. Все идет нормально.

Однако теперь я внес изменение в v1, которое не нужно в v2, но я хочу продолжить объединение других исправлений ошибок. Как мне сказать Git пропустить этот конкретный коммит (или диапазон коммитов), но в дальнейшем я все еще хочу объединить другие исправления ошибок.

Я думал, что git rebase может быть то, что мне нужно, но прочитал документ, и моя голова почти взорвалась.

Я думаю, что мне нужно что-то вроде команды "git sync", которая сообщает git, что две ветви сейчас синхронизированы и в будущем объединяют только коммиты с этой точки синхронизации.

Любая помощь приветствуется.

183
Brad Robinson

Например, если вы хотите объединить большинство, но не все коммиты в ветке "maint", в "master", вы можете сделать это. Это требует некоторой работы - как упоминалось выше, обычный вариант использования - объединение всего из ветки - но иногда случается, что вы внесли изменение в версию выпуска, которая не должна быть интегрирована обратно (возможно, этот код был уже заменен в мастере), так как вы это представляете? Вот оно...

Итак, давайте предположим, что к maint применено 5 изменений, и одно из них (maint ~ 3) не должно быть объединено с master, хотя все остальные должны быть. Вы делаете это в три этапа: на самом деле объединяйте все до этого, говорите git пометить maint ~ 3 как слитые, даже если это не так, а затем объедините остальные. Магия это:

bash <master>$ git merge maint~4
bash <master>$ git merge -s ours maint~3
bash <master>$ git merge maint

Первая команда объединяет все до ваш проблемный коммит в мастер. Сообщение журнала слияния по умолчанию объяснит, что вы объединяете "ветку 'maint' (ранняя часть)".

Вторая команда объединяет проблемный коммит maint ~ 3, но опция "-s ours" говорит git использовать специальную "стратегию слияния", которая, фактически, работает, просто сохраняя дерево, в которое вы сливаетесь, и игнорируя коммиты Вы полностью объединены. Но он все еще делает новый коммит слияния с HEAD и ​​maint ~ 3 в качестве родителей, поэтому график изменений теперь говорит, что maint ~ 3 объединен. Так что на самом деле вы, вероятно, захотите использовать опцию -m и для "git merge", чтобы объяснить, что этот коммит maint ~ 3 фактически игнорируется!

Последняя команда просто объединяет оставшуюся часть maint (maint ~ 2..maint) в master, чтобы вы снова синхронизировались.

270
araqnid

ИМХО, самое логичное, что нужно сделать, это объединить все, а затем использовать git revert (commit_you_dont_want) для его удаления.

Пример:

git merge master
git revert 12345678

Если у вас есть несколько коммитов "to-ignore" или вы хотите отредактировать сообщение об отмене:

git merge master
git revert -n 123456
git revert -n abcdef
git commit -m "... Except commits 123456 and abcdef"

Тогда ваша история может выглядеть так:

| ... Except 123456 and abcdef
|\ Merge branch 'master' into 'your_branch'

Если у вас есть конфликты, связанные ТОЛЬКО с этими фиксациями "игнорировать", вы можете использовать:

git merge master -X ours

Таким образом, ваша версия будет сохраняться над другой. Даже без сообщений об ошибках вы все равно можете "отменить" эти нежелательные коммиты, потому что они могут иметь другие изменения, которые не конфликтовали, и вы все равно их не хотите.

Если у вас есть конфликты, связанные НЕ ТОЛЬКО с фиксацией "игнорировать", вы должны разрешить их вручную, и вам, вероятно, придется разрешать их снова во время возврата.

32
Alexandre T.

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

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

16
Dustin

Походит на классический случай для 'git cherry-pick' https://git-scm.com/docs/git-cherry-pick это именно то, что звучит как

6
Gilbert

Это своего рода реклама моего проекта , которая в основном оборачивает процесс, описанный @araqnid.

Это своего рода помощник, который вводит следующий поток GIT:

  • есть ежедневное/еженедельное уведомление об ожидающих слияниях из ветвей обслуживания в ветку dev/master
  • сопровождающий филиала проверяет статус и сам решает, требуются ли все коммиты, и либо блокирует некоторые из них, либо просит разработчиков заблокировать себя. В конце концов ветка обслуживания сливается с upsteam.

Цитата со страницы проекта:

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

Часто исправления попадают в ветки, в которых сообщалось об ошибке, и затем коммит возвращается обратно в основную ветку.

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

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

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

2
Dmytro

Вместо revert или cherry-pick для этого случая вам нужно получить git, чтобы учесть изменения, которые вы пропускаете, чтобы быть старше, чем те, которые вы сделали.

Так:

  1. объединить последний коммит до коммитов, которые вы хотите пропустить. Это, конечно, объединит все коммиты ранее. git merge ccc
  2. объединить коммиты, которые вы хотите пропустить. git merge fff --no-commit
  3. произведите слияние, отмените все изменения, отмените все изменения. (Возможно, для этого есть надежные команды, но я бы просто выполнил эту часть в пользовательском интерфейсе - как вы знаете, как)
  4. завершить пустое слияние git merge --continue
  5. объединить коммиты ПОСЛЕ того, кого вы хотели пропустить. git merge source-branch-head

После шага 4 git будет считать вашу ветку более новой, чем эта фиксация, поскольку вы уже имели дело с ней (решив сохранить ВАШИ версии вещей).

0
Jason Kleban

Создайте третью ветку для изменений, которые вы хотите в master10, но не в master20. Всегда считайте master10 своим "хозяином", самой стабильной веткой из всех. Ветвь, с которой все остальные ветви должны постоянно синхронизироваться.

0
wilhelmtell