Как я могу толкать внесены изменения, обязуемся удаленного репозитория Git?


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

> 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/'

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

13 539

13 ответов:

я на самом деле один раз толкнул с --force и .git репозиторий и получил ругань Линуса БОЛЬШОЙ. В общем, это создаст много проблем для других людей. Простой ответ "Не делай этого".

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

  1. найти старый коммит, который вы исправили (назовите его old, и мы назовем новую фиксацию, которую вы создали, изменив new).
  2. создать слияние между old и new, запись дерево new, как git checkout new && git merge -s ours old.
  3. объедините это с вашим мастером с git merge master
  4. обновите свой мастер с результатом с git push . HEAD:master
  5. нажмите на результат.

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

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

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

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

git push -f origin master

даже это может не работать, так как Git позволяет удаленным репозиториям отказаться от не-fastforward толкает на дальнем конце с помощью переменной конфигурации 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 что означает push a null branch to the remote side master, т. е. удалить удаленный филиал. Имя ветви без : означает переместить локальную ветвь с заданным именем в удаленную ветвь с тем же именем. master в этой ситуации сокращенно master:master.

Quick rant: тот факт, что никто не опубликовал простой ответ здесь, демонстрирует отчаянную враждебность пользователя, проявляемую git CLI.

после того, как вы разрешили любые конфликты, вы можете нажать еще раз.

Так:

git pull

Если вы получаете ошибки в потяните, может быть, что-то не так в вашей конфигурации локального репозитория (у меня был неправильный ref .раздел ветви 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

который делает следующее:

  • сброс головки ветви к родительской фиксации.
  • припрятать этот последний коммит.
  • принудительное нажатие на пульт. У пульта дистанционного управления теперь нет последней фиксации.
  • поп свой заначку.
  • совершить чисто.
  • нажмите на пульт дистанционного управления.

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

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

# 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-новичок, я думал, что это было полным 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 фиксация вместо 5), но это спасло дневную работу.

Если вы знаете, что никто не вытащил ваш исправленный коммит, используйте на git push.

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

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

если вы не передали код в удаленную ветку (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

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

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

git push origin master -f

или:

git push origin master --force

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

git push -f origin branch_name

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

git pull origin branch_name

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

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

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

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

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