Как объединить конкретный коммит в Git

Я разветвил ветку из репозитория в GitHub и совершил что-то конкретное для меня. Теперь я обнаружил, что оригинальный репозиторий имеет хорошую функцию, которая была в HEAD.

Я хочу объединить его только без предыдущих коммитов. Что мне делать? Я знаю, как объединить все коммиты:

git branch -b a-good-feature
git pull repository master
git checkout master
git merge a-good-feature
git commit -a
git push
19.05.2009 05:27:34
Если вы пытаетесь сделать это в отношении github, эта статья поможет вам в этом. markosullivan.ca/how-to-handle-a-pull-request-from-github
johndpope 23.05.2011 01:10:21
5 ОТВЕТОВ
РЕШЕНИЕ

' git cherry-pick' должен быть ваш ответ здесь.

Примените изменения, внесенные существующим коммитом.

Не забудьте прочитать ответ bdonlan о последствиях выбора вишни в этом посте:
«Вытащить все коммиты из ветви, переместить указанные коммиты в другую» , где:

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

будет выглядеть так:

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

Проблема с этим коммитом в том, что git считает коммиты включающими всю историю до них

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

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

1160
4.04.2020 03:40:33
@ openid000: «более мелкозернистые ветви»: именно это и предлагал bdonlan в своем ответе.
VonC 22.05.2009 08:47:45
Примечание: «git rebase» также меняет SHA-1. Смотрите также "git rebase против git merge ( stackoverflow.com/questions/804115/git-rebase-vs-git-merge ) и" git workflow "( stackoverflow.com/questions/457927/… ) для случаев, когда" git rebase "является законным.
VonC 22.05.2009 08:50:48
Между «мелкозернистыми ветками», «cherry-pick» и «rebase» у вас будут все возможности для управления кодом в ветках с помощью git.
VonC 22.05.2009 08:51:33
@VonC "мелкозернистые ветви" да. У меня было две ветви, и я сделал обновления для конкретного модуля визуализации в одной ветви. Этот модуль не зависел от всего остального кода, поэтому cherry-pick было чертовски удобно применять эти изменения и к другой ветке
Cheeku 29.09.2015 07:08:36
Но обратите внимание, что при слиянии оба коммита C и C преобладают в истории коммитов.
Rahul Shah 11.07.2017 00:12:14

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

Пример: git cherry-pick d42c389f

726
5.02.2015 11:08:49
+1 за ваш прежний пост по сбору вишни ( stackoverflow.com/questions/880957/… ). Я взял на себя смелость скопировать его выдержку в своем ответе выше.
VonC 19.05.2009 10:24:04
Возможно git cherry-pick d42cили git cherry-pick d42c3 будет работать. Git умный. ;)
guneysus 11.02.2015 21:46:19
Роковая: плохая ревизия
Ievgen Naida 25.01.2019 19:31:33
Я только что выполнил эту команду, и она, кажется, сработала, но когда я делаю git status, он говорит «ничего не коммитить, рабочее дерево чистое». Когда я обновляю страницу «Коммиты» на моей веб-странице, она не отображается. Но это появляется, когда я выполняю git log. И я вижу модифицированный код. Может кто-нибудь объяснить, если я должен сделать какие-либо дополнительные шаги?
Ray 29.01.2019 18:36:22
git reset --soft HEAD ~ 1 удалит коммит и покажет добавленные файлы.
Aslam anwer 30.04.2019 09:28:49

Давайте попробуем взять пример и понять:

У меня есть ветвь, скажем, master , указывающая на X <commit-id>, и у меня есть новая ветвь, указывающая на Y <sha1>.

Где Y <commit-id> = <master> ветка коммитов - несколько коммитов

Теперь скажите, что для ветви Y я должен закрыть пробелы в коммитах между веткой master и новой веткой. Ниже приведена процедура, которой мы можем следовать:

Шаг 1:

git checkout -b local origin/new

где local - название филиала. Любое имя может быть дано.

Шаг 2:

  git merge origin/master --no-ff --stat -v --log=300

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

Для получения дополнительной информации и параметров о слиянии Git, пожалуйста, обратитесь к:

git merge --help

Также, если вам нужно объединить конкретный коммит, вы можете использовать:

git cherry-pick <commit-id>
29
5.07.2016 16:17:09
Вы изменили определение Yв своем 3-м предложении? «У меня есть новая ветвь, указывающая на Y» против «Теперь скажем для ветки Y», звучит так, как будто Y был коммитом, а потом стал веткой
Purefan 8.05.2018 10:48:36
как я могу сделать это с определенной точки фиксации ветви, которую я хочу слить
Kulbhushan Singh 22.10.2018 07:04:45

В моем случае использования у нас была аналогичная потребность в CI CD. Мы использовали git flow с ветками Develop и Master. Разработчики могут объединять изменения непосредственно для разработки или посредством запроса извлечения из функциональной ветви. Однако для мастеринга мы автоматически объединяем только стабильные коммиты из ветки разработки через Jenkins.

В этом случае выбор вишни не является хорошим вариантом. Однако мы создаем локальную ветвь из commit-id, затем объединяем эту локальную ветвь с master и выполняем mvn clean verify (мы используем maven). В случае успеха выпустите артефакт рабочей версии для Nexus, используя плагин релиза maven с опцией localCheckout = true и pushChanges = false. Наконец, когда все прошло успешно, нажмите изменения и отметьте источник.

Пример кода:

Предполагая, что вы на мастере, если все сделано вручную. Однако на jenkins, когда вы оформляете репо, вы будете в ветке по умолчанию (master, если настроен).

git pull  // Just to pull any changes.
git branch local-<commitd-id> <commit-id>  // Create a branch from the given commit-id
git merge local-<commit-id>  // Merge that local branch to master.
mvn clean verify   // Verify if the code is build able
mvn <any args> release:clean release:prepare release:perform // Release artifacts
git push origin/master  // Push the local changes performed above to origin.
git push origin <tag>  // Push the tag to origin

Это даст вам полный контроль с бесстрашным адом слияния или конфликта.

Не стесняйтесь советовать в случае, если есть какой-либо лучший вариант.

3
28.11.2019 21:44:10

Ведущие ответы описывают, как применить изменения от конкретного коммита к текущей ветви. Если это то, что вы имеете в виду под словом «как объединить», тогда просто используйте cherry-pick, как они предлагают.

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

Наличие истинной истории слияний может быть желательным, например, если ваш процесс сборки использует преимущества git-предков для автоматической установки строк версий на основе последнего тега (using git describe).

Вместо cherry-pick вы можете сделать фактический git merge --no-commit, а затем вручную настроить индекс, чтобы удалить любые изменения, которые вам не нужны.

Предположим, вы находитесь на ветке Aи хотите объединить коммит в конце ветки B:

git checkout A
git merge --no-commit B

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

(Там может быть простой способ установить состояние рабочего каталога и индекса обратно, как это было до слияния, так что у вас есть чистый лист, на котором можно выбрать коммит, который вы хотели в первую очередь. Но Я не знаю, как добиться этого с чистого листа. git checkout HEADИ git reset HEADоба уберут состояние слияния, нанося поражение цели этого метода.)

Так что вручную отмените нежелательные изменения. Например, вы могли бы

git revert --no-commit 012ea56

за каждый нежелательный коммит 012ea56.

Когда вы закончите настройку, создайте свой коммит:

git commit -m "Merge in commit 823749a from B which tweaked the timeout code"

Теперь у вас есть только то изменение, которое вы хотели, и дерево предков показывает, что вы технически слились с B.

3
22.02.2020 05:15:25