Принудительно "git push" перезаписывать удаленные файлы
Я хочу отправить свои локальные файлы и разместить их на удаленном репо, не сталкиваясь с конфликтами слияния. Я просто хочу, чтобы моя локальная версия имела приоритет над удаленной.
Как я могу сделать это с Git?
7 ответов
Вы должны быть в состоянии заставить вашу локальную ревизию к удаленному репо, используя
git push -f <remote> <branch>
(например git push -f origin master
). Оставляя <remote>
а также <branch>
заставит подтолкнуть все локальные ветви, которые установили --set-upstream
,
Просто предупреждаю, что если другие люди делятся этим хранилищем, их история изменений будет конфликтовать с новой. И если у них есть какие-либо локальные коммиты после точки изменения, они станут недействительными.
Обновление: думал, что я бы добавил примечание. Если вы создаете изменения, которые будут проверять другие, то нередко создается ветка с этими изменениями и периодически обновляется, чтобы держать их в курсе основной ветки разработки. Просто дайте знать другим разработчикам, что это будет происходить периодически, чтобы они знали, чего ожидать.
Обновление 2: из-за растущего числа зрителей я хотел бы добавить дополнительную информацию о том, что делать, когда ваш upstream
действительно испытывает силовой толчок.
Скажем, я клонировал ваш репо и добавил несколько коммитов так:
D ---- E тема / A----B----C разработка
Но позже development
ветвь поражена rebase
, что приведет к тому, что я получу сообщение об ошибке, как при запуске git pull
:
Распаковка предметов: 100% (3/3), сделано. Из <репо-местоположения> * развитие филиала -> FETCH_HEAD Авто-слияние <файлы>КОНФЛИКТ (контент): конфликт слияния в <местоположениях>Автоматическое объединение не выполнено; исправить конфликты, а затем зафиксировать результат.
Здесь я мог бы исправить конфликты и commit
, но это оставило бы меня с ужасной историей коммитов:
C ---- D ---- E ---- F тема / / A----B--------------C'разработка
Это может выглядеть заманчиво для использования git pull --force
но будьте осторожны, потому что это оставит вас с мельчайшими коммитами:
D ---- E тема A----B----C'разработка
Так что, вероятно, лучший вариант сделать git pull --rebase
, Это потребует от меня разрешения любых конфликтов, как раньше, но для каждого шага вместо фиксации я буду использовать git rebase --continue
, В итоге история коммитов будет выглядеть намного лучше:
D '--- E' тема / A----B----C'разработка
Обновление 3: Вы также можете использовать --force-with-lease
опция в качестве "более безопасного" принудительного толчка, как упомянул Кексейк в своем ответе:
Принудительное нажатие с помощью "аренды" позволяет принудительно выполнить принудительное нажатие, если на удаленном компьютере появятся новые коммиты, которых вы не ожидали (технически, если вы еще не загрузили их в ветку удаленного отслеживания), что полезно, если Вы не хотите случайно перезаписывать чужие коммиты, о которых вы даже не знали, и просто хотите переписать свои собственные:
git push <remote> <branch> --force-with-lease
Вы можете узнать больше о том, как использовать
--force-with-lease
прочитав любое из следующего:
Вы хотите, чтобы заставить толкать
Что вы в основном хотите сделать, это принудительно нажать локальную ветвь, чтобы перезаписать удаленную.
Если вы хотите более подробное объяснение каждой из следующих команд, то смотрите мой раздел подробностей ниже. В основном у вас есть 4 различных варианта принудительного нажатия с помощью Git:
git push <remote> <branch> -f
git push origin master -f # Example
git push <remote> -f
git push origin -f # Example
git push -f
git push <remote> <branch> --force-with-lease
Если вы хотите получить более подробное объяснение каждой команды, то посмотрите раздел моих длинных ответов ниже.
Предупреждение: принудительное нажатие перезапишет удаленную ветвь с состоянием ветви, которую вы нажимаете. Убедитесь, что это то, что вы действительно хотите сделать, прежде чем использовать его, иначе вы можете перезаписать коммиты, которые вы на самом деле хотите сохранить.
Сила толкания детали
Указание пульта и ветки
Вы можете полностью указать конкретные ветки и пульт. -f
флаг это короткая версия --force
git push <remote> <branch> --force
git push <remote> <branch> -f
Опуская ветку
Когда ветка для push-ветки пропущена, Git выяснит это на основе ваших настроек конфигурации. В версиях Git после 2.0 новый репо будет иметь настройки по умолчанию, чтобы выдвинуть текущую извлеченную ветку:
git push <remote> --force
в то время как до 2.0 новые репо будут иметь настройки по умолчанию для продвижения нескольких локальных веток. Рассматриваемые настройки являются remote.<remote>.push
а также push.default
Настройки (см. ниже).
Опуская пульт и филиал
Когда и удаленный и ветвь опущены, поведение просто git push --force
определяется вашим push.default
Настройки Git config:
git push --force
Начиная с Git 2.0, по умолчанию
simple
, в основном, просто подтолкнет вашу текущую ветвь к ее удаленной противоположной части. Пульт определяется по веткеbranch.<remote>.remote
и по умолчанию используется исходное хранилище.До Git версии 2.0, настройки по умолчанию,
matching
, в основном, просто выталкивает все ваши локальные филиалы в филиалы с одинаковыми именами на удаленном компьютере (по умолчанию это источник).
Вы можете прочитать больше push.default
настройки по чтению git help config
или онлайн-версию страницы руководства git-config(1).
Сила толкать более безопасно с --force-with-lease
Принудительное нажатие с помощью "аренды" позволяет принудительно выполнить принудительное нажатие, если на удаленном компьютере появятся новые коммиты, которых вы не ожидали (технически, если вы еще не загрузили их в ветку удаленного отслеживания), что полезно, если Вы не хотите случайно перезаписывать чужие коммиты, о которых вы даже не знали, и просто хотите переписать свои собственные:
git push <remote> <branch> --force-with-lease
Вы можете узнать больше о том, как использовать --force-with-lease
прочитав любое из следующего:
Другой вариант (чтобы избежать принудительного толчка, который может быть проблематичным для других участников):
- разместите ваши новые коммиты в отдельной ветке
- сбросить
master
наorigin/master
- объединить вашу выделенную ветку с
master
, всегда сохраняя коммиты из выделенной ветви (что означает создание новых ревизий поверхmaster
который будет отражать вашу выделенную ветку).
Смотрите " git command для создания одной ветви как другой", чтобы узнать о стратегиях имитацииgit merge --strategy=theirs
,
Таким образом, вы можете выдвинуть мастер на дистанцию без необходимости что-либо форсировать.
git push -f немного деструктивен, потому что он сбрасывает все удаленные изменения, которые были сделаны кем-то еще в команде. Более безопасный вариант: {git push --force-with-lease}.
То, что делает {--force-with-lease}, - отказывается обновлять ветку, если мы не ожидаем того состояния; т.е. никто не обновил ветку вверх по течению. На практике это работает путем проверки того, что ссылка на исходный код - это то, что мы ожидаем, потому что ссылки являются хешами и неявно кодируют цепочку родителей в их значение. Вы можете сказать {--force-with-lease}, что именно нужно проверять, но по умолчанию проверит текущий удаленный реф. На практике это означает, что, когда Алиса обновляет свою ветвь и передает ее в удаленный репозиторий, указательная головка ветки будет обновлена. Теперь, если Боб не извлекает данные из пульта, его локальная ссылка на пульт будет устаревшей. Когда он отправляет push, используя {--force-with-lease}, git проверяет локальный ref на новом пульте и отказывается форсировать push. Фактически {--force-with-lease} позволяет принудительно нажимать, только если в это время никто другой не выдвигал изменения на удаленное устройство. Это {--force} с пристегнутым ремнем безопасности.
// make sure your local branch is up to date
git checkout fix-build
git pull origin fix-build
// push your local branch to overwrite remote branch 'main'
git push -f origin fix-build:main
пс. Принятый ответ не сработал для меня. Я не уверен, что это связано с версией Git.
Простые шаги с использованием tortoisegit
GIT дает фиксацию локальных файлов и отправляет их в репозиторий git.
Шаги:
1) stash изменяет имя тайника
2) pull (тянуть)
3) stash pop (тайник поп)
4) зафиксировать 1 или несколько файлов и указать автора и дату набора описания изменений фиксации
5) push (толкать)