Как я могу выдвинуть определенный коммит на удаленный, а не предыдущий коммит?

829

Я сделал несколько коммитов для разных файлов, но пока я хотел бы отправить в мой удаленный репозиторий только определенный коммит.

Это возможно?

Robert23
источник
6
возможный дубликат git: нажмите один коммит
user151019
Смотрите хорошую технику здесь: stackoverflow.com/a/1789142/1579667
Benj

Ответы:

1089

Для того, чтобы подтолкнуть вверх через данность совершала, вы можете написать:

git push <remotename> <commit SHA>:<remotebranchname>

при условии, что <remotebranchname>уже существует на пульте. (Если этого не произойдет, вы можете использовать его git push <remotename> <commit SHA>:refs/heads/<remotebranchname>для автоматического создания.)

Если вы хотите отправить коммит, не нажимая предыдущие коммиты, вы должны сначала использовать git rebase -iего для переупорядочения коммитов .

Джефф Риди
источник
66
git push <remotename> <commit SHA>:<remotebranchname>работает. хитрость заключается в том, чтобы объединить его с тем, git rebase -iчтобы переместить коммит, который вы хотите, в качестве первого коммита, и указать этот коммит-ша
dminer
29
Еще один хороший совет - убедитесь, что вы скопировали SHA коммита, который вы хотите нажать после выполнения этой ребазировки -i, а не раньше, как я только что сделал :)
estan
33
Имейте в виду, что это не удастся, если удаленная ветвь еще не существует. Создание ветки можно сделать с помощью git push <remotename> <commit SHA>:refs/heads/<new remote branch name>. После этого нажмите как ответ описывает.
Уэс Олденбювинг
33
Например, нажать все, кроме последнего коммита, с некоторыми стандартными именами git push origin HEAD~1:master.
бесхитростный шум
3
Также обратите внимание, что если вы уже выдвинули более поздний SHA в эту удаленную ветвь, то вам нужно будет принудительно протолкнуть этот. Используйте -fфлаг.
Ян Воан
79

Другие ответы отсутствуют в описаниях переупорядочения.

git push <remotename> <commit SHA>:<remotebranchname>

будет выдвигать один коммит, но этот коммит должен быть самым старым из ваших локальных, не выдвинутых, коммитов, чтобы его не путали с верхним, первым или концевым коммитом, которые, на мой взгляд, являются неоднозначными описаниями. Для коммита требуется самый старый из ваших коммитов, то есть самый дальний из ваших последних коммитов. Если это не самая старая фиксация, то все фиксации от вашего самого старого локального не выдвинутого SHA к указанному SHA будут отправлены. Чтобы изменить порядок коммитов используйте:

git rebase -i HEAD~xxx

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

Подводя итог, я использовал

git rebase -i HEAD~<number of commits to SHA>
git push origin <post-rebase SHA>:master

отправить один коммит в мою удаленную главную ветку.

Ссылки:

  1. http://blog.dennisrobinson.name/push-only-one-commit-with-git/
  2. http://blog.dennisrobinson.name/reorder-commits-with-git/

Смотрите также:

  1. git: дублирование фиксируется после локальной перебазировки с последующим Pull
  2. Git: Pushing Single Commits, Изменение порядка с rebase, Duplicate Commits
Самуил
источник
3
Кажется, что некоторые источники не могут этого допустить. Например, в GitLab я вижу: «Вы не можете принудительно принудительно вводить push-код в защищенную ветку в этом проекте». Что немного странно, поскольку я не думал, что что-то заставляю, просто делаю нормальный толчок. Есть идеи, как это сделать без «принуждения»?
Эд Авис
1
@ Эд Не должно быть никакой необходимости форсировать толчок. Похоже, у вас есть проблемы с вашей конкретной настройкой git. Может быть, вы перебили удаленный коммит HEAD? Я не знаю, что такое защищенная ветка, звучит как проблема с разрешениями.
Самуил
1
Сэмюэль - это имело бы смысл, но git rebase -i показывает только локальные коммиты, которые позже, чем удаленный HEAD, поэтому я не знаю, как я мог это сделать.
Эд Авис
1
Сэмюэль - действительно, я могу теперь делать частичные толчки, поэтому я не знаю, что пошло не так, но, должно быть, он пытался протолкнуть коммит, не полученный из удаленного HEAD, так или иначе.
Эд Авис,
1
@Ed Вы сказали "git rebase -i показывает только локальные коммиты, которые позже, чем удаленный HEAD", я не думаю, что это правда. Я проверил и смог пройти мимо удаленной ГОЛОВКИ.
Самуэль
25

Я бы предложил использовать git rebase -i; переместите коммит, который вы хотите нажать, на вершину коммитов, которые вы сделали. Затем используйте git logдля получения SHA перебазированного коммита, проверьте его и нажмите на него. Ребаз будет иметь гарантию того, что все остальные ваши коммиты теперь являются дочерними по отношению к тому, который вы нажали, так что будущие толчки тоже будут работать нормально.

Вальтер Мундт
источник
3
Не могли бы вы дать ход полный пример ESP. снова на git logшаг?
Друкс
4
Скажем, у вас есть 3 относительно независимых фиксации с сообщениями «A», «B», «C», зафиксированных в этом порядке, и вы хотите нажать «B». 'git rebase -i' должен получить вас и редактор, перечисляющий все три; переместить B вверх и сохранить / выйти. 'git log --pretty = oneline -n3' будет перечислять B, A, C с хешами перед каждым сообщением, с B теперь последним. 'git checkout -b temp $ hash_of_B; git push 'должен нажать B в этой точке. Тогда вы, вероятно, захотите 'git checkout -b master; git branch -d temp ', чтобы вернуться в ваше предыдущее состояние, предполагая, что вы были в локальной ветке master; заменить в зависимости от обстоятельств.
Вальтер Мундт
1
+1 Вы когда-нибудь сталкивались с «гневом мерзавцев» после rebase-push-rebase? (Возможно, это могло произойти и случайно, верно?)
Друкс
2
Если вы внимательно прочитаете мой ответ, вы увидите, что толчок происходит только после перебазирования, а перебазированный коммит перемещается только над другими коммитами, которые еще не были переданы. После того, как коммит выдвинут, его обычно следует считать установленным в камне; оставь его в покое в будущем. Этот метод только для того, чтобы вы могли отсортировать несколько локальных изменений в хорошем порядке, прежде чем нажимать их. Если вы правильно настроили отслеживание, «git rebase -i» без других аргументов по умолчанию не будет даже показывать вам отправленные коммиты, поэтому он безопаснее от аварий, чем некоторые другие методы.
Уолтер Мундт
21

Cherry-pick лучше всего работает по сравнению со всеми остальными методами, выдвигая конкретный коммит.

Способ сделать это:

Создать новую ветку -

git branch <new-branch>

Обновите новую ветку с вашей исходной веткой -

git fetch

git rebase

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

Вишни подбери то sha idчто ты хочешь сделать толчком -

git cherry-pick <sha id of the commit>

Вы можете получить sha id, запустив

git log

Подтолкни его к своему происхождению -

git push

Беги, gitkчтобы увидеть, что все выглядит так, как ты хотел.

Дэвид
источник
2
Использование git rebase -iбудет идеальным решением, как предложено в вышеупомянутых решениях. Вишневый кир должен использоваться только тогда, когда вы хотите дублировать коммит.
Винай Бхаргав
13

Я полагаю, что вам придется «вернуться» назад к этому коммиту и затем нажать его. Или вы можете cherry-pickзафиксировать в новую ветку и отправить ее в ветку в удаленном хранилище. Что-то вроде:

git branch onecommit
git checkout onecommit
git cherry-pick 7300a6130d9447e18a931e898b64eefedea19544 # From the other branch
git push origin {branch}
Джош К
источник
9
git revert - плохая идея здесь - он создает новый коммит
hasen
1
@hasen: Тогда вы можете просто cherry-pickсовершить коммит, который хотите.
Джош К
4
и возврат, и выбор вишни - плохие идеи. git rebase -i - ваш друг, смотрите ответ Уолтера Мундта ниже.
Николас С
3
@ Николас, почему вишня выбирает плохую идею?
Антуан
3
@ Antoine, обычно вы хотите, чтобы ваша ветка синхронизировалась с той, которую она отслеживает при отправлении. Если вы выбираете «черри», вы делаете копирование / вставку, и в какой-то момент вам придется иметь дело с неперекачиваемой копией. Если вы перебазируете -i, вы выполните «вырезать и вставить» и синхронизируете свою ветку с пультом до того места, где вы хотите.
Николас С
0

Вы также можете в другом каталоге:

  • git clone [ваш репозиторий]
  • Перезаписать каталог .git в вашем исходном хранилище каталогом .git хранилища, которое вы только что клонировали.
  • мерзавец добавить и мерзавец совершить ваш оригинал
NunoSempere
источник