Как `git pull` съел мою домашнюю работу?


53

Я чувствую себя ребенком в кабинете директора, объясняя, что собака съела мою домашнюю работу накануне ее появления, но я смотрю на сумасшедшую ошибку потери данных на лице и не могу понять, как это произошло. Я хотел бы знать, как мерзавец мог съесть мое хранилище целиком! Я много раз вставлял мерзавца, и он никогда не моргал. Я использовал его, чтобы разделить репозиторий 20 Gig Subversion на 27 репозиториев git и отфильтровать их, чтобы распутать беспорядок, и это никогда не потеряло меня. Переполнения всегда есть, чтобы отступить. На этот раз ковер исчез!

С моей точки зрения, все, что я сделал, - это запустил git pullи уничтожил весь мой локальный репозиторий. Я не имею в виду, что это «испортило проверенную версию» или «ветку, на которой я был» или что-то в этом роде. Я имею в виду, что все это ушло .

Вот скриншот моего терминала в инциденте:

снимок экрана

Позволь мне провести тебя через это. Моя командная строка содержит данные о текущем git-репо (используя реализацию vcs_info prezto), чтобы вы могли видеть, когда git-репо исчезло. Первая команда достаточно нормальная:

  » 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-репо. Обратите внимание, что 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, ничего. Пустой.

Мой локальный мерзавец находится на версии 2.0.2. Вот пара моментов из моего git config, которые могут иметь отношение к выяснению того, что произошло:

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

Например, я git pullустановил всегда делать ребазирование вместо слияния, чтобы часть вывода выше была нормальной.

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

Я проверил:

  • Сообщения в dmesg или системный журнал. Ничего, даже отдаленно не актуального.
  • Нет признаков сбоя диска или файловой системы (LVM + LUKS + EXT4 все выглядит нормально). Там нет ничего в потерянном + найдено.
  • Я больше ничего не запускал. В истории нет ничего, что я не показываю выше, и никакие другие терминалы не использовались в течение этого времени. Нет rmкоманд, плавающих вокруг, которые могли бы выполняться в неправильном CWD и т. Д.
  • Выглядывание в другом git-репо в другом каталоге не показывает явной аномалии выполнения git pulls.

Что еще я должен искать здесь?


4
@ Патрик Как я уже объяснил в вопросе, нет .gitне существует. Ничего не значит - то, что раньше было корневым каталогом git, вообще ничего не имеет.
Калеб

2
@Alexander Операция вытягивания нормальная (за исключением того, что это ребаз, а не слияние). Уведомление о принудительном обновлении указывает, что у репо, из которого я берусь, был принудительный толчок, который сбрасывал его из положения, отличного от того, в котором местный репо в последний раз видел его. Это нормально, потому что я синхронизирую активно разрабатываемые и часто перебазируемые материалы между моими компьютерами, а не публичной веткой, которую увидят другие разработчики.
Калеб

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

2
@Caleb Вы действительно должны спросить в списке рассылки git development; Вы можете написать это как отчет об ошибке или просто неформально спросить - все равно так же. Есть некоторые разработчики, которые хорошо знают git - они могут интуитивно понять, что могло произойти. (Если нет, они просто будут спокойно следить за обсуждением.) И они знают, произошло ли это раньше. (Сообщая об этом, существует «официальный» способ сообщать об ошибках для git)
Volker Siegel

7
@Wildcard На самом деле я хотел собрать ответ на этот вопрос, поскольку я действительно выяснил, что произошло. Система недавно вышла из спящего режима, и сеть не работала в течение нескольких дней, прежде чем перешла в спящий режим. Где-то в этом процессе я оставил запущенный процесс pacman, который пытался что-то обновить в системе. Короче говоря, оказывается, что glibc обновлен, а двоичный файл git перезаписан. Из-за того, как он разветвлялся, один экземпляр в итоге отличался от другого, и они ели обед друг друга. Справочник действительно был пустым (не просто appar
Caleb

Ответы:


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 - это make, использующий разные команды вместо одного двоичного файла. git-fetchgit-rebasegit-mergegit gc
Выполняется

2

Возможно, из-за ошибки при определении пути к файлу, который нужно удалить.

Ваш случай напомнил мне прекрасный день, когда мой домашний remove(path)метод пытался удалить корневую папку, потому что заданным параметром была пустая строка, которую ОС исправила (!) Как корневую папку.

Это может быть похожая ошибка. Такой что:

  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. Я удалю свой ответ, так как он не имеет значения.
Routhinator

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

Мне тоже очень любопытно. Будет ли что-нибудь подобное случиться с моими репо.
Routhinator

-1

Похоже , кто - то пытался git push --forceна этом репо, и вы разобрали эти изменения. Попробуйте клонировать репо заново, чтобы вы снова вернулись в чистое рабочее состояние.


1
Вынужденный толчок перебил последнюю горстку коммитов. Это было не то, что я вытащил (рабочий каталог больше не является рабочим каталогом!), И даже если бы его повторное клонирование не имело никакого смысла.
Калеб

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