У меня есть файл, скажем, file.txt. Я сделал git mv file.txt для file1.txt, затем создал новый файл с именем file.txt и работал над ним. К сожалению, я еще не добавил этот файл в git. В любом случае, проблема в том, что я сделал git stash, затем git stash apply, но новый файл .txt исчез... как бы его вернуть?
Странный случай git - git stash, за которым следует git stash, применить потерянные незафиксированные данные?
Ответы (4)
Проблема здесь в основном в непонимании того, что делает git stash save
. Он сохраняет только изменения в отслеживаемых файлах. Неотслеживаемые файлы не сохраняются git stash
. Когда вы переместили файл.txt в файл1.txt, новый файл.txt является неотслеживаемым и не будет сохранен git stash
. Это не ошибка, просто так себя ведет git stash
. Возможно, документация для git stash
должна быть более ясной по этому поводу.
Как указано в документации для git stash save
, он выполнит git reset --hard
после сохранения ваших изменений. Именно git reset --hard
перезаписал новый файл .txt. Кто-то может возразить, что git reset --hard
должен генерировать предупреждение, если неотслеживаемый файл будет перезаписан, но я бы все же не назвал это ошибкой. Он делает то, что должен делать.
Здесь важно понять — и это избавило бы вас от многих проблем — это то, что git stash save
не сохраняет неотслеживаемые файлы (и, вероятно, не должно).
git stash
откатывается и перезаписывает незафиксированные данные, должно быть какое-то уведомление.
- person maček; 10.04.2010
git stash
и повторно применен git stash apply
. Это просто неправильное ожидание. Однако, как вы сказали, я думаю, что было бы разумно получить предупреждение (и запросить подтверждение), если неотслеживаемый файл будет перезаписан git reset --hard
.
- person Dan Moulding; 10.04.2010
git status
говорит о состоянии рабочего дерева после того, как исходный файл перемещен и создан новый — это в значительной степени говорит само за себя.
- person Dan Moulding; 10.04.2010
git reset --hard
, а не с git stash save
, поскольку первая перезаписывает неотслеживаемый файл без предупреждения.
- person Dan Moulding; 10.04.2010
git stash
- это пользовательская операция, которая теряет содержимое файла, так что это ошибка в git stash
. Он перезаписывает измененный файл версией HEAD с расширением reset --hard
. Поскольку тайник сбрасывается на отслеживаемую версию файла, он должен убедиться, что он сохранил любую версию, которую он перезаписывает. git stash
должно быть безопасной операцией, это не похоже на reset --hard
, который просит git выбросить вещи. Я не считаю, что наблюдаемое поведение тайника приемлемо.
- person CB Bailey; 10.04.2010
git reset --hard
делает это, и это причина, по которой git stash save
перезаписывает неотслеживаемый файл. git stash save
не сохраняет неотслеживаемые файлы. В момент запуска git stash save
в этом случае Git считает файл.txt неотслеживаемым файлом. Так что это не и не должно сохраняться. Лучшее, что вы можете получить, — это предупреждение о том, что неотслеживаемый файл будет перезаписан. Но это git reset --hard
нужно изменить, если мы хотим получить такое поведение.
- person Dan Moulding; 10.04.2010
git stash
сохранил файл, ему необходимо, чтобы этот файл имел представление BLOB-объектов в репозитории. Новый файл file.txt никогда не добавлялся в индекс, поэтому Git никогда не создавал большой двоичный объект для этого файла. Поскольку у него нет большого двоичного объекта для файла, он никоим образом не может сохранить файл в тайнике. Вы предлагаете Git начать отслеживать файл (создав для него большой двоичный объект), который никогда не добавлялся явно. Это просто не то, как это предназначено для работы.
- person Dan Moulding; 10.04.2010
git stash
сохранит ваши локальные изменения перед выполнением reset --hard
. Удаление файла, а затем повторное добавление файла с другим содержимым, безусловно, является локальным изменением. git stash; git stash apply
должен быть неактивным (хорошо, строго сброс git). Ваш аргумент о том, что это не капля, явно фальшивка. Если у вас есть неустановленные локальные изменения файлов, которые не были удалены из индекса, git stash
создает новые большие двоичные объекты для измененных файлов. git stash
уже выполняет git add -u
, так почему бы ему не создавать большие двоичные объекты для всех файлов, которые он удаляет?
- person CB Bailey; 11.04.2010
git stash
сохранить новый файл .txt, вам нужно сначала git add
его. Это слишком много?
- person Dan Moulding; 11.04.2010
git stash
ведет себя именно так, как рекламируется. Ни в коем случае ни в коем случае он не должен стирать изменения. Но если он собирается стереть файл, о котором он ничего не знает (неотслеживаемый файл), то я лично думаю, что было бы неплохо, если бы он выдал предупреждение (так же, как git checkout
делает в тех же обстоятельствах). Я абсолютно не согласен с тем, что git stash
должен сохранять неотслеживаемые файлы при любых обстоятельствах.
- person Dan Moulding; 11.04.2010
git status
показал бы новый файл как измененный, но не обновленный. Но это не так. Это ясно показывает, что Git считает этот файл неотслеживаемым. Кажется, вы утверждаете, что сломано не только git stash
, но и git status
.
- person Dan Moulding; 11.04.2010
git reset --hard
удалит неотслеживаемые файлы без предупреждения, вызывает сомнения.
- person Dan Moulding; 11.04.2010
git stash
должен отменить все изменения между HEAD и текущим рабочим деревом, а также сбросить индекс на HEAD. git stash
, за которым сразу следует git stash apply
, должно сбросить рабочее дерево до состояния, в котором оно было до тайника. Для меня они являются ключевыми и неизбежно приводят к тому, что если HEAD содержит файл с определенным содержимым, а версия рабочего дерева имеет другое содержимое, то состояние файла рабочего дерева должно быть сохранено независимо от того, содержит ли индекс этот файл или нет. версия этого файла или нет.
- person CB Bailey; 11.04.2010
Это похоже на серьезную (т.е. потерю данных) ошибку в тайнике. Пожалуйста, сообщите об этом. К сожалению, я не верю, что есть способ вернуть новый file.txt
.
Теперь эта ошибка исправлена в git >=1.7.1.1.
в будущем используйте git stash -u
для хранения незафиксированных файлов (http://www.kernel.org/pub/software/scm/git/docs/git-stash.html). Думаю, вы можете сделать это, начиная с git версии 1.7.
Этот пост предназначен для того, чтобы просто проиллюстрировать процесс воссоздания, не вдаваясь в комментарии. Примечание. Использование Git версии 1.7.0.2.
Чтобы воссоздать:
~/test $ git init
~/test $ echo "hello" > file.txt
~/test $ git add .
~/test $ git commit -m "init commit"
~/test $ git mv file.txt file1.txt
~/test $ echo "new data" > file.txt
~/test $ git stash
~/test $ git stash apply
~/test $ cat file.txt
cat: file.txt: No such file or directory
~/test $ cat file1.txt
hello