Как мне отправить исправленный коммит в удаленный репозиторий Git?
-
05-07-2019 - |
Вопрос
Когда я немного поработал со своим исходным кодом, я сделал свою обычную фиксацию, а затем переместился в удаленный репозиторий.Но потом я заметил, что забыл упорядочить свой импорт в исходном коде.Итак, я выполняю команду изменить, чтобы заменить предыдущую фиксацию:
> 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/'
Что мне следует делать?(Я могу получить доступ к удаленному репозиторию.)
Решение
Я на самом деле однажды запустил репозиторий --force
и .git
, и меня отчитал Линус БОЛЬШОЕ ВРЕМЯ . В целом это создаст много проблем для других людей. Простой ответ: & Quot; не делайте этого & Quot;.
Я вижу, что другие так или иначе дали рецепт для этого, поэтому я не буду повторять их здесь. Но вот совет для восстановления ситуации после того, как вы выдвинули исправленный коммит с помощью --force (или + master).
<Ол>git reflog
, чтобы найти старый коммит, который вы изменили (назовите его old
, и мы назовем новый коммит, который вы создали, изменив new
). git checkout new && git merge -s ours old
и git merge master
, записав дерево git push . HEAD:master
, например <=>. Тогда люди, которые были достаточно неудачны, чтобы основывать свою работу на коммите, который вы стерли, исправив и форсировав толчок, увидят, что в результате слияния вы увидите, что вы поддерживаете <=>, а не <=>. Их более поздние слияния не приведут к конфликтам между <=> и <=>, которые возникли в результате ваших изменений, поэтому им не придется страдать.
Другие советы
Вы видите функцию безопасности 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
имеет нулевой local_ref, что означает перемещение нулевой ветви на удаленную сторону master
, т.е. удаление удаленной ветви. Имя ветви без :
означает передачу локальной ветви с заданным именем в удаленную ветку с тем же именем. master:master
в этой ситуации - сокращение от <=>.
Быстрая тирада:Тот факт, что никто не опубликовал здесь простой ответ, демонстрирует отчаянную враждебность пользователей, проявляемую Git CLI.
В любом случае, "очевидный" способ сделать это, предполагая, что вы не пытались принудительно нажать, - сначала потянуть.Это вытягивает изменение, которое вы исправили (и поэтому которого больше нет), чтобы оно появилось у вас снова.
Как только вы разрешите все конфликты, вы можете нажать еще раз.
Итак:
git pull
Если вы получаете ошибки при извлечении, возможно, что-то не так в конфигурации вашего локального репозитория (у меня была неправильная ссылка в разделе ветки .git / config).
И после
git push
Возможно, вы получите дополнительный коммит с темой, рассказывающей о "Тривиальном слиянии".
Краткий ответ: не выдвигайте исправленные коммиты в публичное репо.
Длинный ответ. Несколько команд Git, таких как git commit --amend
и git rebase
, на самом деле переписывают граф истории. Это нормально до тех пор, пока вы не опубликовали свои изменения, но как только вы это сделаете, вам действительно не стоит копаться в истории, потому что, если кто-то уже получил ваши изменения, тогда, когда они попытаются снова вытащить, он может потерпеть неудачу. , Вместо внесения изменений в коммит, вы должны просто сделать новый коммит с изменениями.
Однако, если вы действительно хотите отправить исправленный коммит, вы можете сделать это следующим образом:
$ git push origin +master:master
Ведущий знак +
заставит произойти толчок, даже если это не приведет к & «ускоренной перемотке вперед!»! совершить. (Ускоренная фиксация происходит, когда изменения, которые вы отправляете, являются прямым потомком изменений, уже находящихся в публичном репо.)
Вот очень простой и понятный способ протолкнуть свои изменения после того, как вы уже внесли commit --amend
:
git reset --soft HEAD^
git stash
git push -f origin master
git stash pop
git commit -a
git push origin master
Который выполняет следующее:
- Сбросьте заголовок ветви до родительского коммита.
- Спрячьте этот последний коммит.
- Принудительно нажмите на пульт дистанционного управления.У удаленного устройства теперь нет последней фиксации.
- Открой свою заначку.
- Совершайте все чисто.
- Нажмите на пульт дистанционного управления.
Не забудьте изменить "origin" и "master", если применяете это к другому филиалу или удаленному компьютеру.
Я решил эту проблему, отбросив мой локальный исправленный коммит и добавив новые изменения сверху:
# 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
У меня была такая же проблема.
- Случайно внес изменения в последнюю фиксацию, которая уже была отправлена
- Внес много изменений локально, зафиксировал около пяти раз
- Попытался нажать, получил ошибку, запаниковал, объединил удаленное, получил много не моих файлов, нажал, сбой и т.д.
Как новичок в Git, я думал, что это было завершено ФУБАР.
Решение:Примерно так, как предложил @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 коммит вместо 5), но это сэкономило день работы.
Если вы не отправили код в удаленную ветку (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?
Важное примечание. При непосредственном использовании принудительного нажатия вы можете столкнуться с проблемами кода, которые другие разработчики работают в той же ветке. Поэтому, чтобы избежать этих конфликтов, вам нужно извлечь код из своей ветки перед тем, как сделать принудительное нажатие :
git commit --amend -m "BRANCH-NAME : your new message"
git pull origin BRANCH-NAME
git push -f origin BRANCH-NAME
Это лучший метод при изменении сообщения о коммите, если оно уже было отправлено.
Если вы знаете, что никто не снял ваш коммит без изменений, используйте параметр --force-with-lease
git push
.
В TortoiseGit вы можете сделать то же самое в " Push ... " параметры " Force: может отменить " и проверка " известные изменения ".
Force (может отменить известные изменения) разрешает удаленное хранилище принять более безопасный толчок без ускоренной перемотки вперед. Это может привести к потере коммитов в удаленном репозитории; используйте это с осторожностью. Это может предотвратить потерю неизвестных изменений от других людей на пульте. Он проверяет, указывает ли ветвь сервера на тот же коммит, что и на ветку удаленного отслеживания (известные изменения). Если да, будет выполнен принудительный толчок. В противном случае он будет отклонен. Поскольку в git нет тегов удаленного отслеживания, теги нельзя перезаписать с помощью этой опции.
Вот очень простой и понятный способ протолкнуть свои изменения после того, как вы уже внесли git add "your files"
и git commit --amend
:
git push origin master -f
или:
git push origin master --force
Вы получаете эту ошибку, потому что Git Remote уже имеет эти файлы коммитов. Вы должны принудительно нажать на ветку, чтобы это работало:
git push -f origin branch_name
Также убедитесь, что вы извлекаете код из удаленного узла, поскольку кто-то из вашей команды мог отправить его в ту же ветку.
git pull origin branch_name
Это один из случаев, когда мы вынуждены принудительно выдавать коммит на удаленный доступ.
Мне нужно было решить эту проблему с помощью извлечения из удаленного репозитория и устранения возникших конфликтов слияния, фиксации, а затем отправки. Но я чувствую, что есть лучший способ.
Я просто продолжал делать то, что мне сказал Мерзавец.Итак:
- Не могу нажать из-за измененной фиксации.
- Я делаю рывок, как было предложено.
- Сбой слияния.поэтому я исправляю это вручную.
- Создайте новый коммит (с пометкой "объединить") и нажмите на него.
- Кажется, это работает!
Примечание:Измененный коммит был последним.
Вот, как я исправил редактирование в предыдущем коммите:
<Ол>git stash
Теперь твоя рабочая копия чиста в состоянии твоего последнего коммита. git commit --all --amend
Ваш редактор появится с запросом на сообщение журнала (по умолчанию старое сообщение журнала). Сохраните и выйдите из редактора, когда вы довольны им.
Новые изменения добавляются в старый коммит. Убедитесь сами с помощью git log
и git diff HEAD^
Повторно примените ваши скрытые изменения, если они были сделаны: git stash apply