Як `git pull` їв домашнє завдання?


53

Я відчуваю себе дитиною в кабінеті директора, пояснюючи, що собака їв мою домашню роботу в ніч до того, як це відбулося, але я дивлюсь на якусь божевільну помилку втрати даних в обличчя, і я не можу зрозуміти, як це сталося. Я хотів би знати, як git міг їсти моє сховище ціле! Я багато разів прокладав git через винищувач, і він ніколи не моргнув. Я використав це для того, щоб розділити репо з 20 Gig Subversion на 27 git repos і фільтрувати розгалужену туш для них, щоб розплутати безлад, і він ніколи не втратив байт на мені. Рефлог завжди є, щоб відпасти. Цього разу килим пропав!

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

Ось знімок екрана мого терміналу при інциденті:

постріл екрану інциденту

Дозвольте мені пройти вас через це. Мій командний рядок включає дані про поточну репортажну програму git (використовуючи vcs_info реалізацію prezto), щоб ви могли побачити, коли git repo зник. Перша команда достатньо нормальна:

  » caleb » jaguar » ~/p/w/incil.info » ◼  zend ★ »
❯❯❯ git co master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

Там ви можете побачити, що я був на «zend» гілці, і перевірив майстра. Все йде нормально. Ви побачите в запиті перед моєю наступною командою, що вона успішно перемикає гілки:

  » caleb » jaguar » ~/p/w/incil.info » ◼  master ★ »
❯❯❯ git pull
remote: Counting objects: 37, done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 37 (delta 25), reused 0 (delta 0)
Unpacking objects: 100% (37/37), done.
From gitlab.alerque.com:ipk/incil.info
 + 7412a21...eca4d26 master     -> origin/master  (forced update)
   f03fa5d..c8ea00b  devel      -> origin/devel
 + 2af282c...009b8ec verse-spinner -> origin/verse-spinner  (forced update)
First, rewinding head to replay your work on top of it...
>>> elapsed time 11s

І просто так воно пропало. Проміжок часу маркер виводиться перед наступним підказкою, якщо минуло більше 10 секунд. Git не дав жодного результату, окрім повідомлення про те, що він перемотується для відтворення. Немає ознак того, що він закінчився.

Наступний рядок не містить даних про те, на якій гілці ми знаходимося, чи про стан git.

Помітивши це не вдалося, я, очевидно, намагався запустити ще одну команду git, щоб мені сказали, що я не перебуваю в git repo. Зверніть увагу, що PWD не змінився:

  » caleb » jaguar » ~/p/w/incil.info »
❯❯❯ git fetch --all
fatal: Not a git repository (or any parent up to mount point /home)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).

Після цього огляд навколо показав, що я перебуваю в абсолютно порожньому каталозі. Нічого. Немає каталогу ".git", нічого. Порожній.

Мій локальний git є у версії 2.0.2. Ось декілька ласощів з мого конфігурації git, які можуть бути доречні для з'ясування того, що сталося:

[branch]
        autosetuprebase = always
        rebase = preserve
[pull]
        rebase = true
[rebase]
        autosquash = true
        autostash = true
[alias]
        co = checkout

Наприклад, я git pullвстановив, що завжди потрібно робити ребауз замість злиття, так що частина вихідних даних є нормальною.

Я можу відновити дані. Я не думаю, що не було жодних git-об'єктів, окрім якихось неважливих сташів, які не підштовхувались до інших репостів, але я хотів би знати, що сталося .

Я перевірив:

  • Повідомлення в dmesg або системному журналі. Нічого навіть віддалено не має значення.
  • Немає вказівки несправності накопичувача або файлової системи (LVM + LUKS + EXT4 все виглядає нормально). У втраченому + знайденому немає нічого.
  • Я більше нічого не бігав. Нічого в історії я не показую вище, і жоден інший термінал не використовувався протягом цього часу. Немає rmплаваючих команд навколо, які могли б виконатись у неправильному КЗД тощо.
  • Переміщення іншого git repo в іншому каталозі не показує видимих ​​аномалій виконання git pulls.

Що ще я повинен шукати тут?


4
@Patrick Як я вже пояснював у запитанні, жодного .gitне існує. Нічого не робить - те, що раніше було кореневою каталогом git, взагалі нічого не містить.
Калеб

2
@Alexander Операція потягування нормальна (крім того, що це перезавантаження, а не злиття). Повідомлення про примусове оновлення вказує на те, що репо, з якого я тягнув, мав силовий поштовх, який скинув його з іншого положення, ніж місцевий репо востаннє бачив його. Це нормально, тому що я синхронізую активно розроблений і часто переобладнаний матеріал між власними комп’ютерами, а не публічним відділенням, яке бачать інші розробники.
Калеб

3
@Caleb ваш запит на оболонку включає вказівку гілки git, що означає, що формування PS1 включає команди git, які не відображаються у вашому журналі. Вони можуть принципово змінити картину і можуть стати джерелом випуску. Вам слід оновити питання, що точно описує, як формується ваш запит на оболонку, які команди виконуються, щоб отримати поточну гілку, і переглянути, як вони могли зіпсувати ваше репо.
Netch

2
@Caleb Ви дійсно повинні запитати у списку розсилки git development; Ви можете написати це як повідомлення про помилку або просто запитати неофіційно - все одно це те саме. Є деякі розробники, які добре знають git - вони, ймовірно, можуть за допомогою інтуїції сказати, що могло статися. (Якщо ні, вони просто спокійно слідкують за дискусією.) І вони знають, чи відбулося це раніше. (Повідомляючи про це, існує "офіційний" спосіб повідомляти про помилки за git)
Volker Siegel,

7
@Wildcard Насправді я мав намір зібрати відповідь на це, як я насправді зрозумів, що сталося. Нещодавно система вийшла зі сну, і мережа існувала днями, перш ніж вона перейшла у сон. Десь у цьому процесі я залишив запущений процес pacman, який намагався щось оновити в системі. Якщо коротко розповісти, виявляється, що glibc оновився, а біт git був перезаписаний. Через те, як він розщепився, один екземпляр виявився іншим, ніж інший, і вони їли обід один одного. Довідник справді був порожнім (не лише appar
Калеб

Відповіді:


6

Так, gitїв домашнє завдання. Все це.

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

  1. Команда оновлення системи ( pacman -Syu) була видана за кілька днів до цього інциденту.
  2. Розширене відключення мережі означало, що залишається повторна спроба завантаження пакетів. Розчарований через відсутність Інтернету, я поклав систему спати і лягав спати.
  3. Через кілька днів система прокинулася, і вона знову почала знаходити та завантажувати пакети.
  4. Завантаження пакунків завершено десь перед тим, як я трапився з цим сховищем.
  5. Установка системи glibc оновилася після git checkoutта перед git pull.
  6. gitДвійкова був замінений після git pullпочатку і до його завершення.
  7. І на сьомий день gitвідпочивав від усіх своїх праць. І видалили світ, тому всі інші теж повинні були відпочити.

Я не знаю точно, що сталося з перегоном, що спричинило це, але міняти бінарні файли в середині операції, безумовно, не приємно, ані умови, які можна перевірити / повторювати. Зазвичай копія запущеного бінарного файлу зберігається в пам'яті, але gitце дивно, і я щось впевнений у тому, як він перероджує версії себе, я впевнений, що це призвело до цього безладу. Очевидно, він мав загинути, а не знищити все, але саме так і сталося.


1
git міг не вдатися, оскільки git робиться за допомогою команд diff, а не однієї двійкової. Простий витяг git-fetchgit-rebasegit-mergegit gc
гетів

2

Можливо, не вдалося визначити шлях файлу для видалення.

Ваш випадок нагадав мені прекрасний день, що коли мій саморобний remove(path)метод намагався видалити кореневу папку, оскільки даний параметр був порожнім рядком, який ОС виправляла (!) Як кореневу папку.

Це може бути схожий git bug. Такий, що:

  1. Команда Rebase хотіла видалити файл типу remove(project_folder + file_path)(псевдокод)
  2. Якось тоді file_pathбуло порожньо.
  3. Команда оцінюється як щось подібне remove(project_folder)

1

Якщо пощастить, ви можете виправити це за допомогою наступної команди:

git reset --hard ORIG_HEAD  

Коли починаються потенційні небезпечні зміни, git переставляє ваш поточний стан в ORIG_HEAD. З його допомогою ви можете скасувати злиття або відновлення.

Посібник з Git: скасування об'єднання


4
Я не думаю, що ти прочитав ціле запитання. Таке виправлення зовсім не підлягає сумніву, оскільки немає метаданих git . Здійснення такого скидання вимагає існування поточного каталогу .git та деяких об'єктів у ньому для роботи. Я не маю нічого. Це не просто заплутаний робочий каталог, це вже не сховище будь-якого типу.
Калеб

Ах, вибачте. Це дуже незвично. Якщо git repo відсутній, я вважаю, що відновлення не буде, якщо ви не затіняєте файли в Linux та не створюєте резервні копії файлів fs. Я видалю свою відповідь, оскільки це не має значення.
Ротатор

Так, я знаю, що це незвичайна проблема (і у мене є резервні копії). Моє запитання тут полягає в тому, як воно пішло не так ... де шукати помилку в git чи моєму драйвері файлової системи або що-небудь ще, що могло б пошкодити їсти каталог у середині такої операції.
Калеб

Мені теж дуже цікаво. Чи буде ненависть, щоб щось подібне трапилось із моїм репостом.
Ротатор

-1

Схоже, хтось побіг git push --forceна це репо, і ти зняв ці зміни. Спробуйте клонувати репо в свіжому вигляді, що знову повернеться до чистого робочого стану.


1
Вимушений поштовх знизив останню жменю комітетів Це я не випустив (робочий каталог більше не працює робочим каталогом!), І навіть якщо він був повторно клонований, це не мало б сенсу.
Калеб

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