Вытащить все коммиты из ветки, переместить указанные коммиты в другую

102

У меня есть следующие ветки:

  • master
  • production

и следующие удаленные ветки:

  • origin/master
  • origin/production

У меня есть сценарий, который извлекает origin/masterветку и получает различие того, что изменилось из моей последней fetch ( log -p master..origin/master). Потом сливаю origin/master.

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

Я хочу отправить успешные коммиты - и только их - в производственную ветку, а затем, конечно же, в origin/production.

Как я могу это сделать?

Кроме того, у меня запущено 2 сценария: один, который извлекает origin/master, отправляет данные в базу данных и выполняет слияние, а другой, который я сейчас пишу, должен будет подтолкнуть успешные коммиты.

Я хотел бы, чтобы эти 2 сценария работали, избегая при этом состояния гонки / конфликта слияния. Поскольку я хочу работать только с указанными коммитами, может быть, есть способ избавиться от коммитов, которые мне не нужны?

Сильвен
источник
Что вы имеете в виду под «успешными коммитами»?
bdonlan
тот, который был рассмотрен и отмечен как успешный. здесь это не имеет значения, важно то, что есть коммиты, которые я хочу сохранить и переместить в другую ветку, а другие, от которых я хочу избавиться / игнорировать.
Sylvain

Ответы:

315

Я думаю, вы ищете термин «вишенка». То есть возьмите одну фиксацию из середины одной ветки и добавьте ее в другую:

A-----B------C
 \
  \
   D

становится

A-----B------C
 \
  \
   D-----C'

Это, конечно, можно сделать с помощью команды git cherry-pick.

Проблема с этим коммитом в том, что git считает, что коммиты включают всю предшествующую им историю - таким образом, если у вас есть три таких коммита:

A-----B-----C

И попробуйте избавиться от B, вам нужно создать совершенно новый коммит, например:

A-----------C'

Где C 'имеет другой идентификатор SHA-1. Точно так же Cherry выбор фиксации из одной ветки в другую в основном включает создание патча, а затем его применение, что также приводит к потере истории.

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

Возможно, лучший способ справиться с этим - иметь более мелкозернистые ветви. То есть, вместо того, чтобы просто иметь 'master', иметь 'featureA', 'bugfixB' и т. Д. Выполняйте проверку кода для всей ветки за раз - где каждая ветка очень сосредоточена на выполнении только одной задачи - а затем объедините это одна ветка, когда вы закончите. Это рабочий процесс, для которого предназначен git, и в чем он хорош :)

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

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

бдонлан
источник
Что касается моего второго вопроса, я просто хочу убедиться, что процессы получения изменений (1-й сценарий) и отправка заданных коммитов в другое место (2-й сценарий) могут работать без состояния гонки / конфликта слияния при работе с разными ветвями. Но, в конце концов, я полагаю, что это не имеет значения, поскольку я могу объединить 2 сценария в один, так что 2 сценария не будут работать одновременно :)
Сильвен
9
«Это изменение идентификаторов коммитов, помимо прочего, нарушает
Нарек
5
@Narek Он, вероятно, имеет в виду, что изменения в фиксации C 'будут конфликтовать с такими же изменениями в фиксации C, когда вы объедините вторую ветвь. Это следствие потери истории за коммитом C.
bytefu
1
«И попробуйте избавиться от B» - почему вы пытаетесь избавиться от B?
d512
3
@ user1334007, он имеет ввиду, что раньше было ABC. Теперь, из-за того, что вы выбрали C, ваша ветка - AD-C, которая больше не содержит B.
AnneTheAgile
1

Я понимаю, что это старый вопрос, но он упоминается здесь: Как слить конкретный коммит в Git

Следовательно, новый ответ: используйте ветки функций и запросы на вытягивание.

Как это выглядит, где fA - это фиксация с функцией A, а fB - это фиксация с функцией B:

            fA   fC (bad commit, don't merge)
           /  \ /
master ----A----B----C
                \  /
                 fB

Запросы на вытягивание связаны с функциональностью GitHub, но на самом деле я имею в виду только то, что кто-то несет ответственность за объединение веток функций в master.

MattJenko
источник