Скидання Git - твердий та перехід до віддаленого сховища


199

У мене було сховище, яке мало погані помилки (D, E і F для цього прикладу).

ABCDEF майстер та походження / майстер

Я спеціально змінив локальне сховище за допомогою git reset --hard. Я взяв гілку перед скиданням, тому тепер у мене є репо, яке виглядає так:

A-B-C master  
     \ D-E-F old_master

A-B-C-D-E-F origin/master

Тепер мені були потрібні деякі з цих поганих порушень, тому я вишнею вибрав потрібні мені шматочки та зробив нові нові зобов’язання, тому тепер у мене є місце на наступному:

A-B-C-G-H master
     \ D-E-F old_master

Тепер я хочу підштовхнути такий стан справ до віддаленого репо. Однак, коли я намагаюся зробити git pushGit ввічливо, видає мені пензлик:

$ git push origin +master:master --force  
Total 0 (delta 0), reused 0 (delta 0)  
error: denying non-fast forward refs/heads/master (you should pull first)  
To git@git.example.com:myrepo.git  
! [remote rejected] master -> master (non-fast forward)  
error: failed to push some refs to 'git@git.example.com:myrepo.git'  

Як змусити віддалений репо приймати поточний стан місцевого репо?


2
Це "майже" дублікат декількох "як я підштовхую змінені питання історії", наприклад, дивіться відповідь тут stackoverflow.com/questions/253055/…
CB Bailey

2
Це правда, і я шукав відповідь у StackOverflow перед публікацією. Однак мій пошук виявив лише відповіді, в яких git push - forfor виправило проблему. Дякуємо за посилання на ваш пост :)
robertpostill

2
Ви незабаром (git1.8.5, Q4 2013) зможете зробити git push -forceбільш ретельно .
VonC

Відповіді:


286

Якщо змушення натискання не допомагає (" git push --force origin" або " git push --force origin master" повинно бути достатньо), це може означати, що віддалений сервер відмовляється від нешвидкісних натискань вперед або через змінну config.denyNonFastForwards (див. Опис на сторінці git config ). через гачок оновлення / попереднього отримання.

Зі старшим Git ви можете обійти це обмеження, видаливши " git push origin :master" (див. ':' Перед назвою гілки), а потім знову створити " git push origin master" дану гілку.

Якщо ви не можете змінити це, єдиним рішенням буде замість того, щоб переписати історію, щоб створити зміни, що повертають зміни в DEF :

ABCDEF - [(DEF) ^ - 1] майстер

ABCDEF походження / магістр

2
@ JakubNarębski, спасибі get revert HEAD~Nдопомогли. N- кількість комітів. Наприклад, якщо мені знадобиться попередня фіксація, я скористаюсьgit revert HEAD~1
Максим Дмитрієв

1
І майте на увазі, що ви зламаєте всіх інших місцевих майстрів, роблячи це.
Том Бріто

24

Щоб доповнити відповідь Якуба, якщо у вас є доступ до віддаленого сервера git в ssh, ви можете зайти в віддалений каталог git і встановити:

user@remote$ git config receive.denyNonFastforwards false

Потім поверніться до місцевого репо, повторіть спробу виконувати свої зобов'язання --force:

user@local$ git push origin +master:master --force

І нарешті поверніть налаштування сервера у вихідний захищений стан:

user@remote$ git config receive.denyNonFastforwards true

Дивіться також pete.akeo.ie/2011/02/denying-non-fast-forward-and.html для детальної інформації щодо цього джерела .
hlovdal

Детальні вказівки щодо відключення використання програми denyNonFastForwards viнадаються на цьому повідомленні "SO":
stackoverflow.com/a/43721579/2073804

2

Замість того, щоб виправляти свою "головну" гілку, легше поміняти її своїм "бажаним господарем", перейменувавши гілки. Дивіться https://stackoverflow.com/a/2862606/2321594 . Таким чином, ви навіть не залишите жодного сліду з декількох журналів відновлення.


1

Весь бізнес, що перезавантажував git, для мене виглядав набагато складніше.

Тож я щось зробив, щоб отримати свою папку src у тому стані, який я мав кілька комісій тому

# reset the local state
git reset <somecommit> --hard 
# copy the relevant part e.g. src (exclude is only needed if you specify .)
tar cvfz /tmp/current.tgz --exclude .git  src
# get the current state of git
git pull
# remove what you don't like anymore
rm -rf src
# restore from the tar file
tar xvfz /tmp/current.tgz
# commit everything back to git
git commit -a
# now you can properly push
git push

Таким чином, стан справ у src зберігається у файлі tar, і git змушений приймати цей стан без надто сильного зміцнення, в основному каталог src замінюється на стан, який він мав кілька комітетів тому.


0

Для користувачів GitHub це працювало для мене:

  1. У будь-яких правилах захисту гілок, де ви хочете внести зміни, переконайтеся, що ввімкнено Allow force pushs
  2. git reset --hard <full_hash_of_commit_to_reset_to>
  3. git push --force

Це дозволить "виправити" історію філій на вашій локальній машині та сервері GitHub, але кожен, хто синхронізував цю гілку з сервером з моменту поганої фіксації, матиме історію на своїй локальній машині. Якщо вони мають дозвіл на перехід до відділення безпосередньо, ці комірки відображатимуться в режимі резервного копіювання під час синхронізації.

Все, що потрібно зробити, - це git resetкоманда зверху "виправити" гілку на своїй локальній машині. Звичайно, їм слід насторожено ставитися до будь-яких місцевих зобов'язань, зроблених у цій галузі після цільового хешу. Виберіть / резервуйте вишню та повторно застосуйте їх за потребою, але якщо ви перебуваєте у захищеному відділенні, то кількість людей, які можуть взяти на себе зобов’язання безпосередньо, ймовірно обмежена.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.