Как я могу надавить исправленную фиксацию на удаленный репозиторий Git?

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

> git commit --amend

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

> git push origin
To //my.remote.repo.com/stuff.git/
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to '//my.remote.repo.com/stuff.git/'

Что мне делать? (Я могу получить доступ к удаленному репозиторию.)

475
задан Spoike 31 окт. '08 в 13:23
источник поделиться

13 ответов

Я на самом деле однажды нажал репозиторий --force и .git и получил ругание от Linus BIG TIME. В общем, это создаст массу проблем для других людей. Простой ответ: "Не делай этого".

Я вижу, что другие давали рецепт для этого, так что я не буду повторять их здесь. Но вот подсказка, чтобы оправиться от ситуации после того, как вы вытолкнули исправленную фиксацию с помощью --force (или + master).

  • Найдите старый коммит, который вы внесли в него (назовите его old, и мы выберем новый комманд, который вы создали, изменив new).
  • Создайте слияние между old и new, записав дерево new, например git checkout new && git merge -s ours old.
  • Объедините это с вашим мастером с помощью git merge master
  • Обновите свой мастер с помощью результата git push . HEAD:master
  • Вывести результат.

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

371
ответ дан gitster 11 янв. '09 в 10:36
источник поделиться

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

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

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

git push -f origin master

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

 ! [remote rejected] master -> master (non-fast forward)

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

git push origin :master
git push origin master

В общем случае последний параметр git push использует формат <local_ref>:<remote_ref>, где local_ref - это имя ветки в локальном репозитории, а remote_ref - имя ветки в удаленном репозитории. Эта пара команд использует два сокращения. :master имеет значение null local_ref, что означает наложение нулевой ветки на удаленную сторону master, то есть удаление удаленной ветки. Имя ветки без : означает, что локальная ветвь с указанным именем перенаправляется в удаленную ветку с тем же именем. master в этой ситуации является коротким для master:master.

218
ответ дан Charles Bailey 01 нояб. '08 в 0:58
источник поделиться

Быстрый разглагольствование: тот факт, что никто не опубликовал простой ответ, демонстрирует отчаянную враждебность пользователя, проявленную с помощью Git CLI.

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

Как только вы разрешите какие-либо конфликты, вы можете нажать еще раз.

Итак:

git pull

Если вы получаете ошибки в pull, возможно, что-то не так в вашей конфигурации локального репозитория (у меня был неверный ref в разделе .git/config).

И после

git push

Возможно, вы получите дополнительную фиксацию с предметом, рассказывающим о "Trivial merge".

184
ответ дан Tim Band 22 сент. '09 в 13:46
источник поделиться

Краткий ответ: не нажимайте исправленные фиксации на публичное репо.

Длинный ответ: несколько команд Git, таких как git commit --amend и git rebase, фактически переписывают график истории. Это прекрасно, пока вы не опубликовали свои изменения, но как только вы это сделаете, вы действительно не должны обманывать историю, потому что, если кто-то уже получил ваши изменения, тогда, когда они попытаются снова вытащить, Вместо того, чтобы вносить изменения в коммит, вы должны просто сделать новую фиксацию с изменениями.

Однако, если вы действительно хотите надавить исправленное сообщение, вы можете сделать это следующим образом:

$ git push origin +master:master

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

86
ответ дан mipadi 31 окт. '08 в 17:35
источник поделиться

Вот простой и чистый способ сделать ваши изменения после того, как вы уже сделали commit --amend:

git reset --soft HEAD^
git stash
git push -f origin master
git stash pop
git commit -a
git push origin master

Что делает следующее:

  • Reset ответвление ветки головки на родительский.
  • Нажмите последнее коммит.
  • Принудительное нажатие на пульте дистанционного управления. Теперь удаленный компьютер не имеет последнего фиксации.
  • Попасть в свой кошелек.
  • Читай чисто.
  • Нажмите на пульте дистанционного управления.

Не забудьте изменить "origin" и "master", если применить это к другой ветке или удаленному устройству.

20
ответ дан Faiza 21 июня '15 в 17:41
источник поделиться

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

# Rewind to commit before conflicting
git reset --soft HEAD~1

# Pull the remote version
git pull

# Add the new commit on top
git add ...
git commit
git push
16
ответ дан bara 24 сент. '12 в 18:46
источник поделиться

У меня была та же проблема.

  • Случайно скорректирована последняя фиксация, которая уже была нажата
  • Сделано много изменений локально, совершено в пять раз
  • Пытался нажать, получить ошибку, запаниковать, объединить удаленный доступ, получить много не-моих файлов, нажал, не удалось и т.д.

В качестве Git -newbie, я думал, что он завершен FUBAR.

Решение. Несколько иначе, как @bara предложила + создать локальную ветвь резервного копирования

# Rewind to commit just before the pushed-and-amended one.
# Replace <hash> with the needed hash.
# --soft means: leave all the changes there, so nothing is lost.
git reset --soft <hash>

# Create new branch, just for a backup, still having all changes in it.
# The branch was feature/1234, new one - feature/1234-gone-bad
git checkout -b feature/1234-gone-bad

# Commit all the changes (all the mess) not to lose it & not to carry around
git commit -a -m "feature/1234 backup"

# Switch back to the original branch
git checkout feature/1234

# Pull the from remote (named 'origin'), thus 'repairing' our main problem
git pull origin/feature/1234

# Now you have a clean-and-non-diverged branch and a backup of the local changes.
# Check the needed files from the backup branch
git checkout feature/1234-gone-bad -- the/path/to/file.php

Возможно, это не быстрое и чистое решение, и я потерял свою историю (1 commit вместо 5), но он сохранил дневную работу.

7
ответ дан davisca 20 февр. '14 в 13:24
источник поделиться

Если вы знаете, что никто не потянул ваше исправление без изменений, используйте параметр --force-with-lease git push.

В TortoiseGit вы можете сделать то же самое в настройках "Push..." "Force: May discard" и проверка "известных изменений".

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

3
ответ дан ShawnFeatherly 07 июня '16 в 3:03
источник поделиться

Вот простой и чистый способ внести изменения после того, как вы уже сделали git add "your files" и git commit --amend:

git push origin master -f

или

git push origin master --force
2
ответ дан Marwen Bkh 18 янв. '16 в 11:29
источник поделиться

Если вы не нажали код на удаленную ветку (GitHub/Bitbucket), вы можете изменить сообщение фиксации в командной строке, как показано ниже.

 git commit --amend -m "Your new message"

Если вы работаете над определенной ветвью, сделайте следующее:

git commit --amend -m "BRANCH-NAME: new message"

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

Пожалуйста, прочитайте весь ответ, прежде чем делать это

git commit --amend -m "BRANCH-NAME : your new message"

git push -f origin BRANCH-NAME                # Not a best practice. Read below why?

Важное примечание:. Когда вы используете принудительное нажатие, вы можете столкнуться с проблемами кода, которые другие разработчики работают над одной ветвью. Поэтому, чтобы избежать этих конфликтов, вам нужно вытащить код из своей ветки, прежде чем нажимать force:

 git commit --amend -m "BRANCH-NAME : your new message"
 git pull origin BRANCH-NAME
 git push -f origin BRANCH-NAME

Это наилучшая практика при изменении сообщения фиксации, если оно уже было нажато.

2
ответ дан Packer 13 янв. '15 в 10:20
источник поделиться

Вы получаете эту ошибку, потому что у Git remote уже есть эти файлы фиксации. Вы должны принудительно нажать на ветку, чтобы это работало:

git push -f origin branch_name

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

git pull origin branch_name

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

1
ответ дан Praveen Dhawan 21 янв. '16 в 9:35
источник поделиться

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

1
ответ дан Spoike 31 окт. '08 в 14:39
источник поделиться

Я просто продолжал делать то, что сказал мне Git. Итак:

  • Невозможно нажать из-за исправления.
  • Я делаю попытку, как предполагалось.
  • Ошибка слияния. поэтому я исправляю его вручную.
  • Создайте новую фиксацию (помеченную "merge" ) и нажмите его.
  • Кажется, что это работает!

Примечание. Измененная фиксация была последней.

1
ответ дан Rolf 02 дек. '16 в 19:29
источник поделиться

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