Як я можу відновити помилковий майстер походження git push -f?


93

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

Чи можна повернути назад? Я розумію, що всі попередні гілки були перезаписані за допомогою -fопції, тому, можливо, я зіпсував свої попередні редакції.


Відповіді:


54

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

Якщо у вас правильне джерело, тоді ви можете просто натиснути його на пульт з --forceопцією. Git не буде видаляти жодні гілки, якщо ви цього не наказали. Якщо ви насправді втратили коміти, перегляньте цей корисний посібник з відновлення комітів . Якщо ви знаєте SHA-1 комітів, які вам потрібні, то, мабуть, ви в порядку.

Найкраще: зробити резервну копію всього і подивитися, що все ще є у вашому локальному сховищі. Зробіть те ж саме на пульті, якщо це можливо. Використовуйте, git fsckщоб побачити, чи можете ви відновити речі, і перш за все НЕ запускайтеgit gc .

Перш за все, ніколи не використовуйте цю --forceопцію, якщо ви насправді не справді це маєте на увазі.


64
Ви можете, найімовірніше, просто поглянути на рефологи, щоб визначити, де спочатку були віддалені гілки. Наприклад, git reflog show remotes/origin/master. Ви повинні бачити там свій поштовх; коміт у попередньому рядку - там, де він був до того, як ви його зіпсували. Потім ви можете просто підсунути цю версію (з --force) до початку і повернутися туди, де ви були!
Cascabel

@ David: О. Ви не зазначили у своєму запитанні, що у вас не було репо. (Це, звичайно, те, чого ви ніколи не хочете робити.) Якщо у вас є доступ до файлової системи там, куди ви натиснули, ви все одно можете все це зробити.
Cascabel

1
@David: Так. Завжди добре мати свій поточний каталог як частину вашого підказки, щоб уникнути подібного.
Cascabel

1
@Jefromi Я думаю, що те, що ви сказали, є фактичним відповіддю: Навіть зі старою версією (не git fetchвидаленою тривалий час) ви можете відобразити рефлог сторони GitHub і відновити!
nh2

1
Де ця відповідь @Jefromi? Я не бачу того користувача, якого згадували на цій сторінці за межами цієї теми коментарів.
Дон МакКерді,

47

Якщо ви знаєте хеш коміту, це легко, просто відтворіть свою гілку.

5794458...b459f069 master -> master (forced update)

Видалити віддалену гілку:

git push origin :master

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

git checkout 5794458
git branch master
git push origin master

28

Рішення вже згадано тут

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master

Дякую, це спрацювало для мене. Я не мав доступу до видалення master, тому затверджений коментар не вдався.
Анді,

Так, і git reflog show remotes/origin/masterякщо необхідний git reflog (як згадував @Cascabel вище)
Йодер,

2
Це правильна відповідь, дякую за посилання на правильну.
Noitidart

6

Якщо ви не перебуваєте в тому локальному репо, звідки прийшов примусовий натиск, на початковому рівні / рівні майстра відновити неможливо. Але якщо вам пощастило використовувати GitHub або GitHub для підприємств , ви можете переглянути REST API і отримати загублений коміт як патч, приклад:

  1. Перерахуйте події та знайдіть довгий формат коміту sha1

https://api.github.com/repos/apache/logging-log4j2/events

  1. Завантажте загублений коміт і отримайте відповідний патч у json-шляху .files [] / patch

https://api.github.com/repos/apache/logging-log4j2/commits/889232e28f3863d2a17392c06c1dd8cac68485de

  1. Нанесіть місцево і натисніть ще раз

git застосувати patch.patch && git commit -m "відновлений коміт" && git push origin master


4

Інший спосіб відновити втрачений коміт або навіть зрозуміти, які комітети були втрачені, якщо попереднє натискання було зроблено не з вашого місцевого репо, - це переглянути вашу машину CI.

Якщо у вас є робота, яка перевіряє головну гілку після кожного коміту (або серії послідовних комітів), яку ви повинні мати, ви можете подивитися, що вона тестувала останньою. Це коміт, який вам потрібно відновити.

Машина CI може навіть зберігати локальний клон репо, з якого ви можете виконати це відновлення.

Джерело: ймовірно безперервна доставка: Надійні випуски програмного забезпечення за допомогою автоматизації побудови, тестування та розгортання (Серія підписів Аддісона-Веслі (Фаулер))


3

Так, ви можете відновити коміти після git push -f your_branch

Текст із док :

Обрізати записи, старші за вказаний час. Якщо ця опція не вказана, час закінчення береться із налаштування конфігурації gc.reflogExpire, яке, у свою чергу, за замовчуванням становить 90 днів. --expire = всі записи чорносливу незалежно від їх віку; --expire = ніколи не вимикає обрізання доступних записів (але див. --expire-unreachable).

Отже, ви можете зробити:

1- git reflog

введіть тут опис зображення

2 - ви вибираєте Head_Number, чи хочете ви його відновити git reset –hard HEAD@{HEAD-NUMBER}

введіть тут опис зображення

3- Ви можете побачити всі коміти на цій сторінці git cherry -v branch_name

4- врешті-решт ви повинні змусити штовхнути git push -f branch_name

АБО

1- отримати номер SHA від вашого клієнта GIT (інтерфейс)

git reset --hard commit_SHA

2- силовий поштовх

git push -f your_branch

Сподіваюся, це допомагає


2

Я зробив те саме, скасувавши останній натиск лише на один файл. Закінчилося поверненням до початкового стану сховища. Я використовував команди git від Linus, оскільки мав локальну копію в Linux. На щастя, ця копія все ще була цілою.

Все, що я зробив, було (після несамовито зробивши ще кілька копій місцевого репо):

git add .
git status

(там говорилося, що origin / master передував 68 комітів, чудово ... це були всі коміти, які я видалив)

git remote set-url origin <GIT_SSH_URL>
git push

І все відновилось так, як було до того, як я зробив сильний поштовх. Найголовніше, що слід пам’ятати, - це ніколи не робити перевірку на git. після того, як ти з силою штовхнув. Але найкраща практика - відключити опцію push. Я більше ніколи не використовую його. Вивчив мій урок !!


0

Тут ви можете прочитати рішення https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

Мені допоміг другий. Я зробив неправильні ці команди

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

Після цих команд я втратив три коміти. Щоб їх відновити, я звернувся до терміналу, де я помилково зробив `` git pull '' і побачив там вихід, як

60223bf ... 0b258eb деяка гілка -> походження / якась гілка

Другий хеш 0b258eb був саме тим, що мені потрібно. Отже, я взяв цей хеш і видаю команду

git push --force origin 0b258eb:some-branch

0

Для людей, які потрапили в справді погані ситуації, як я (наприклад, якщо bad objectпід час запуску з’являються помилки git reset --hard):

Я написав сценарій під назвою treeaver, який витягує всі ваші файли з GitHub API в крайньому випадку. Ось як ним користуватися:

  1. Клонуйте treesaverсценарій і cdдо нього.
  2. Знайдіть SHAрядок дерева, яке ви хочете відновити, звернувшись https://api.github.com/repos/<your_username_or_org>/<repo>/events.
  3. У payloadвластивості, що відповідає вашій push-події, знайдіть те, до якого commitви хочете повернутися, і натисніть на нього url.
  4. Під commit.tree, скопіюйте tree«S url.
  5. Біжи python3 main.py <tree_url> <path_to_save_to>.

Наприклад, у моєму випадку я б запустив:

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

Звичайно, PR вітаються.

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