Відкат локального та віддаленого сховища git на 1 комітку


188

Я читав подібні дописи на цю тему, і не можу за все життя зрозуміти, як це зробити правильно.

Я зареєстрував близько 1000 файлів, які я не хочу, і мені краще не доведеться пройти 1by1 та видалити їх із репо.

  • У мене віддалений masterВідділення.
  • У мене є місцевий masterвідділення.

Вони обоє на одній редакції.

Я хочу відкатати мій пульт на 1 фіксацію.

Скажіть, моя історія masterє A--B--C--D--E.
Я хочу відкатати місцеве місце D.
Потім натисніть на віддалений, щоб мій поточний хеш став D як віддаленим, так і локальним.

У мене виникають проблеми з цим.
Я використовую Git Tower, але мені комфортно з командним рядком. Будь-яка допомога?

ОНОВЛЕННЯ: Чудові коментарі нижче. Використання скидання, здається, частково не рекомендується, особливо якщо сховище надається спільним з іншими користувачами. Який найкращий спосіб скасувати зміни попередньої комісії без використання жорсткого скидання ? Чи є спосіб?


Я оновив свою відповідь, щоб "скасувати зміни попередньої комісії без використання жорсткого скидання".
VonC

3
Використовуйте git revertдля роботи без жорстких скидів і без занепокоєння користувачів.
користувач562374

2
Можливий дублікат видалення
комітетів

Відкотуючи пульт дистанційного керування, це відлякує, але якщо це те, що ти хочеш зробити, зроби це. Є сотні способів зробити це, але результат був би однаковий на стороні сервера.
FelipeC

Відповіді:


307

Якщо ще ніхто не витягнув ваше віддалене репо, ви можете змінити свою гілку HEAD і примусити натиснути її на вказане віддалене репо:

git reset --hard HEAD^ 
git push -f 

(або, якщо у вас є прямий доступ до віддаленого репо, ви можете змінити його посилання HEAD, навіть якщо це голе репо )

Зауважте, що, як коментує чужа технологія у коментарях нижче , у Windows (CMD сесія), вам знадобиться ^^:

git reset --hard HEAD^^
git push -f 

Оновлення з 2011 року:
використання git push --force-with-lease( яке я тут представлений, представлене в 2013 році з Git 1.8.5) є більш безпечним.

Див Schwern «s відповідь на ілюстрації.


Що робити, якщо хтось уже витягнув репо? Що б я тоді робив?

Тоді я б запропонував щось, що не переписує історію:

  • git revert локально ваш останній фіксатор (створення нового зобов’язання, яке відміняє те, що було зроблено попереднім)
  • натисніть "повернути", породжене git revert.

1
Що робити, якщо хтось уже витягнув репо? Що б я тоді робив?
Джаміс Чарльз

1
@gwho створює філію? Ні, це не переміщує ШОЛУ гілки, але ви все ще в тій же гілці. Однак, оскільки поштовх вже не швидкий вперед, так, вам потрібно змусити його натиснути.
VonC

1
чи є спосіб дізнатися, чи хтось витягнув репо?
Пінкертон

4
У Windows символ ^ використовується для продовження рядка та для виходу з символу, зробивши команду: git reset --hard HEAD ^^
Alien Technology

1
@AlienTechnology Використовуючи Powershell, у Windows 10 мені довелося лише вводити reset --hard HEAD^та не reset --hard HEAD^^скидати останню команду.
Гаспаччо

58

Встановіть локальну гілку на одну версію назад ( HEAD^означає одну версію назад):

git reset --hard HEAD^

Натисніть зміни на походження:

git push --force

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

Виконуючи це за допомогою, --forceуказує git перезаписатись HEADу віддалений репо, без поваги до цього.


1
Я б запропонував не називати це поверненням, оскільки це специфічний термін із дуже різним значенням у git.
Каскабель

@Jefromi: Дякую за підказку. Відредаговано.
eckes

Чудова відповідь. Я читав, що використання скидання, здається, частково не рекомендується, особливо якщо сховище надається іншим користувачам. Чи є більш чіткий спосіб зробити це, що скасовує всі ваші попередні зміни комісії?
Джаміс Чарльз

Будь обережний! Закрийте свої незавершені зміни або втратили їх
Носов Павло,

Круто. Отже, чи означає це, що коли ми це робимо git push origin master, Git може створити нову команду на віддаленій основі, оскільки місцева гілка випереджає щонайменше один раз? Крім того, останні повинні суттєво відрізнятися від того, на що вказує голова на віддаленому репо?
MadPhysicist

18

Якщо ви хочете скасувати останню передачу, прослухайте:

Крок 1:

Перевірте свої місцеві комісії з повідомленнями

$ git log

Крок 2:

Видаліть останню комісію, не скидаючи зміни з місцевої гілки (або головного)

$ git reset HEAD^

АБО, якщо ви не хочете, щоб останні файли фіксації та прослуховування оновлень виконувались

$ git reset HEAD^ --hard

Крок 3:

Ми можемо оновлювати файли та коди, і знову потрібно натиснути з силою, щоб вона видалила попередню команду. Це збереже нові зобов'язання.

$ git push origin branch -f

Це воно!


Це не повернення комітету, а його заміна. Будь ласка, не плутайте нас із новичками Git, не зловживаючи звичайними умовами.
Suncat2000

7

Ввівши команду нижче, ви зможете побачити історію git počin -

$ git журнал

Скажімо, ваша історія на цій конкретній гілці схожа на - commit_A, commit_B, commit_C, commit_D. Де, commit_D - це остання передача, і тут залишається HEAD. Тепер, щоб видалити останню комісію з локального та віддаленого, потрібно зробити наступне:

Крок 1: Видаліть останню фіксацію локально -

$ git скидання - тверда голова ~

Це змінить ваш прихильний HEAD для commit_C

Крок 2: Відсуньте зміни на нову комісію HEAD на віддалений

$ git push origin + HEAD

Ця команда видалить останнє посвідчення з віддаленого.

PS ця команда тестується на Mac OSX і повинна працювати і в інших операційних системах (не претендуючи на інші ОС)



3

Ось оновлена ​​версія процедури, яка є більш безпечною.

git reset --hard HEAD^ 
git push --force-with-lease

git push -fнерозбірливо замінить віддалений сховище власними змінами. Якщо хтось інший підштовхнув зміни, вони будуть втрачені.git push --force-with-leaseбуде натискати вашу базу даних лише тоді, коли сховище буде таким, як ви очікували. Якщо хтось уже натиснув, ваш поштовх не вдасться.

Дивіться –сила вважається шкідливою; розуміння git-примусу з орендою .

Я рекомендую це згладжувати як repush = push --force-with-lease.

Що робити, якщо хтось уже витягнув репо? Що б я тоді робив?

Скажи їм git pull --rebase=merges. Замість а git fetch originі git merge origin/masterбуде git fetch originі git rebase -r origin/master. Це дозволить переписати будь-які їхні локальні зміни, masterщо додаються до нової знижки origin/master.-rзбереже будь-які злиття, які вони, можливо, здійснили.

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

[pull]
        rebase = merges

1
Домовились і схвалили. На мій захист моя стара відповідь 2011 року була написана за два роки до введення --force-with-leaseваріанту.
VonC

Я думав , що я зробив це вже (вчора): stackoverflow.com/posts/4647362/revisions
VonC

1

Я вирішив проблему, як і ваша, за допомогою цих команд:

git reset --hard HEAD^
git push -f <remote> <local branch>:<remote branch> 

0

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

git reset --soft HEAD^

Це працює, оскільки немає спроби змінити неіснуючий робочий каталог. Для отримання більш детальної інформації див. Оригінальну відповідь:

Як я можу відключити останню команду в голому сховищі git?


0

Я просто хотів також видалити останню комісію з віддаленої та чіткої історії фіксації. Наступні спрацювали як шарм

git reset --hard HEAD^ 
git push -f 

Але чим «наступне» відрізняється від моєї відповіді вище ?
VonC

0

Шлях до скидання голови та повернення до попереднього фіксації - через

$ git reset HEAD^ --hard
$ git push <branchname> -f

Але іноді це може бути прийнято у віддаленій гілці:

To ssh:<git repo>
 ! [rejected]        develop -> develop (non-fast-forward)
error: failed to push some refs to 'ssh:<git repo>'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

то інший спосіб - це

git revert HEAD
git push <remote branch>

Це чудово працює.

ПРИМІТКА: пам’ятайте, якщо git push -f <force>не вдалося, а потім намагаєтеся відновити. Зробіть git pullпопередньо, щоб віддалений та локальний синхронізувались, а потім спробуйте git revert.
Перевірте, git logчи переконайтесь, що віддалений та локальний місце знаходяться в одній точці фіксації з тим же SHA1.

git revert 
A --> B --> C -->D
A--> B --> C --> D --> ^D(taking out the changes and committing reverted diffs)

0

на місцевого господаря

git reflog
-- this will list all last commit
  e.g Head@{0} -- wrong push
      Head@{1} -- correct push  
git checkout Head@{1} .
  -- this will reset your last modified files

git status 
git commit -m "reverted to last best"
git push origin/master

Не потрібно хвилюватися, потягнув чи ні інших.

Готово!


0

Якщо ви хочете лише видалити останню команду з віддаленого сховища, не псуючись з вашим локальним сховищем, ось один лайн:

git push origin +origin/master~:master

Для цього використовується такий синтаксис:

git push <remote> <refspec>

Ось, <remote>є originі<refspec> має наступну структуру:

+origin/master~:master

Деталі можна знайти в git-push(1). Попереднє +означає «примусити цю рефлекс», а інша частина означає «від origin/master~до master(віддаленого origin)». Не важко знати, що origin/master~це останнє зобов’язання раніше origin/master, правда?


0

для мене працює ці дві команди:

git checkout commit_id
git push origin +name_of_branch

0

Ви також можете зробити це:

git reset --hard <commit-hash>
git push -f origin master

і всі інші, хто отримав останні погані зобов'язання, скидають налаштування:

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