Это не совсем ответ. К сожалению, не ответ. В общем, Git не должен был потерять ваши файлы, если вы явно не сказали это. Есть несколько способов сказать, Git потерять мои файлы для меня . Не видя точного набора команд, которые вы выполнили, никто не может дать вам ничего, кроме общих советов.
В общем случае извлечение или объединение, которое приведет к потере несохраненной работы, должно завершиться неудачей:
$ git merge
Updating 51ebf55b93..98cedd0233
error: Your local changes to the following files would be overwritten by merge:
Makefile
Please commit your changes or stash them before you merge.
Aborting
, когда git pull
выдает такое же сообщение на моем компьютере, работающем Git 2.24.0.
Некоторые более ранние версии Git будут выдавать другую ошибку, а некоторые действительно древние Версии Git действительно иногда разрушали ваше рабочее дерево, если у вас была незафиксированная работа. Вы не упоминаете, какая у вас версия Git, но если она не ниже Git 2.0, это не должно быть проблемой.
Тем не менее, я рекомендую избегать git pull
, git pull
выполняет две команды Git. Первый просто git fetch
. Например, git pull origin
работает git fetch origin
; работает git pull origin master
работает git fetch origin master
; и выполнение git pull
без опций запускает git fetch
без опций.
Опасная команда секунда или, ну, в общем, опасная слишком сильная слово: команда second может испортить вашу собственную работу. Всегда безопасно запускать git fetch
. 1 Узнайте, как читать то, что печатает git fetch
- это немного сбивает с толку, но это все значит. Подробности см. Ниже.
Вторая команда, которая запускает git fetch
, по умолчанию git merge
. Узнайте, что делает git merge
, и как это влияет на ваше текущее рабочее дерево. Изучите его параметры: --ff-only
, --no-ff
и т. Д.
Вы можете выбрать git pull
run git rebase
в качестве второй команды. Узнайте, что делает git rebase
, и как это влияет не только на ваше текущее рабочее дерево, но также и на коммиты, которые вы перебазируете в процессе. Узнайте его параметры, такие как -i
для интерактивной перебазировки. Вы узнаете, что git rebase
действует как серия повторных команд git cherry-pick
, 2 , использующих режим Git detached HEAD . 3
Затем, после запуска git fetch
и просмотра того, что сделал git fetch
, решите, хотите ли вы посмотреть поступившие коммиты и хотите ли вы объединить - с --ff-only
или --no-ff
Или хотите перебазировать. Теперь у вас есть пространство и время для запуска git log
, если вы хотите, и пространство и время для решения вопроса о rebase vs merge.
Как только вы очень знакомы со всеми этими элементами, и почти уверены в том, что произошло в любом хранилище, из которого вы будете git fetch
, , затем , становится безопасным заблаговременно выбирать слияние с ребасом и использовать удобные ярлыки git pull
для запустить git fetch
, а затем сразу же запустить вторую команду.
1 Если вы возитесь с внутренними настройками git fetch
, вы можете сделать это небезопасным , Думайте об этом как о перемонтировании ваших выключателей света так, чтобы стена около выключателя была наэлектризована. Если вы не нарушите настройку go, git fetch
будет в безопасности. Если вы это сделаете, это на вас. 10
2 Один вид перебазирования действительно использует git cherry-pick
. Другой использует git format-patch
и git apply
вместо этого. Этот второй тип перебазирования в большинстве случаев не так хорош, но работает на go быстрее, так что раньше он использовался по умолчанию, но Git 2.26 собирается изменить значение по умолчанию для использования метода cherry-pick.
3 Перебазировка может остановиться в середине, и вам нужна помощь, чтобы это исправить. Когда это происходит, Git продолжает оставаться в этом режиме HEAD. Следовательно, вы должны узнать, что такое отдельный режим HEAD.
Что git fetch
делает
Помните, что Git на самом деле означает commits . Каждый коммит содержит полный и полный снимок всех ваших файлов. И каждый коммит имеет некоторые метаданные: некоторую информацию о коммите, это не часть зафиксированных данных, но которую Git хочет или должен сохранить для вас. Каждый коммит получает уникальный идентификатор ha sh: большую некрасивую строку букв и цифр, 4 , а не просто простое число, просто считающее (1, 2, 3, ...).
Настоящая магия c коммитов с га sh ID - и причина, по которой он должен быть таким большим и уродливым, - в том, что он уникален среди каждого Git хранилища повсюду. Помните, что у вас есть не только ваш Git репозиторий, либо, может быть, несколько, у всех остальных есть их репозитории. Есть еще Git в origin
. Это хранилище, которое вы клонировали, когда запускали:
git clone <url>
Ваш Git создал новый пустой хранилище, вставил в него URL-адрес, который вы дали, под именем origin
, а затем вызвал другой Git по этому URL. Затем этот другой Git предложил вашему Git свои коммиты, сообщив вашему Git о его именах ветвей (и именах тегов, и других именах, но мы сконцентрируемся на именах веток здесь ). Ваши Git получили Git, которые дали вам все их коммитов, а ваши Git поместили все этих коммитов в вашу database-of- все-фиксации. Затем ваши Git взяли их имена ответвлений и скопировали их, чтобы сделать ваши удаленные слежения имен.
Их master
стали вашими origin/master
. Их develop
, если они были, стали вашими origin/develop
. Шаблон здесь прост: для каждой ветви, которую они имеют, ваш Git создает вариант с префиксом origin/
. В этом имени ваш Git хранит га sh ID, который, как говорит их Git, идет вместе с их именами ветвей.
Короче говоря, ваши имена для удаленного слежения помнят, каковы были их имена ветвей.
Но вы клонировали этот Git репозиторий секунд a go. Или, может быть, даже минуты, или часы, или (ужас) дни или недели. С тех пор многое произошло! (В некоторых случаях активный репозиторий может получать десятки коммитов каждые несколько секунд.)
Итак, чтобы получить из них новый материал, вы запускаете:
git fetch origin
(или просто git fetch
, который обычно по умолчанию использует origin
). Ваш Git вызывает их Git, как это было раньше. Он заставляет их перечислять имена своих ветвей (и теги, и другие имена), как и раньше. Их master
может быть другим сейчас! Если это так, они могут иметь коммиты, которых нет у вашего Git. Ваш Git теперь получает от своих Git новых новых коммитов *1170*, которые у вас есть. 5 Ваш Git добавляет их к вашему коллекция, и теперь у вас есть их - и теперь ваш Git обновляет ваши имена для удаленного слежения .
У меня есть клон (ну, один из нескольких) официального * Ядро 1447 *, которое я часто обновляю, на удобной тестовой машине. Давайте запустим git fetch
на этом и посмотрим:
$ git fetch
remote: Enumerating objects: 243814, done.
remote: Counting objects: 100% (243814/243814), done.
remote: Compressing objects: 100% (45189/45189), done.
remote: Total 243814 (delta 198891), reused 242574 (delta 198039)
Receiving objects: 100% (243814/243814), 76.86 MiB | 4.94 MiB/s, done.
Resolving deltas: 100% (198891/198891), completed with 12626 local objects.
From git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
0f1a7b3fac05..5ad0ec0b8652 master -> origin/master
* [new tag] [snip lots of new tags]
Мы видим здесь кучу сообщений. Первые несколько начинаются с remote:
. На самом деле это сообщения, сгенерированные их Git, которые наши Git просто копируют, чтобы мы могли их видеть. Они говорят о перечислении, подсчете и сжатии объектов . Эти объекты являются внутренним представлением, которое Git использует для каждого из своих объектов базы данных: коммитов, деревьев, больших двоичных объектов и аннотированных тегов. Каждый коммит использует некоторое количество деревьев и BLOB-объектов для хранения своих файлов в виде мгновенного снимка. Коммиты могут делиться деревьями и BLOB-объектами для экономии места: если коммит повторно использует файл или целое дерево, полное файлов, из более раннего или более позднего коммита, они просто делятся своими деревьями и / или BLOB-объектами.
Шаг подсчета подсчитывает, сколько из этих объектов у меня есть, а у меня нет, которые они собираются отправить. В общем, они не будут отправлять те, которые я делаю . 6 Таким образом, этот подсчет произошел для многих коммитов и их файлов, а также для некоторых аннотированных тегов (материал new tag
выше) и насчитал почти четверть миллиона объектов.
Затем они сжали некоторые из этих объектов - в данном случае около 20% объектов (которые обычно составляют гораздо больший процент от общего объема передачи по сети) и отправили их на мой Git. Теперь мы выходим из строк с префиксом remote:
, где мои Git воссоздали исходные объекты и добавили их в мой репозиторий.
Последнее, мой Git обновил мое имя для удаленного слежения, origin/master
, исходя из их master
. Это действительно важная строка:
0f1a7b3fac05..5ad0ec0b8652 master -> origin/master
Два идентификатора ha sh здесь:
0f1a7b3fac05
: мой origin/master
удерживается этот ха sh ID до мой git fetch
обновил его; 5ad0ec0b8652
: мой origin/master
держал этот ха sh ID после мой git fetch
обновил его.
После этого мы видим их имя ветви, master
, затем эту стрелку ASCII ->
, затем мое имя для удаленного отслеживания, origin/master
.
Это говорит о том, что мой origin/master
был настроен для добавления новых коммитов, без отмены каких-либо существующих коммитов. Если я хочу узнать , сколько коммитов я только что получил, я могу теперь посчитать их:
$ git rev-list --count 0f1a7b3fac05..5ad0ec0b8652
31244
Итак, с тех пор, как в последний раз я запускал git fetch
, я только что выбрал еще 31 244 коммитов, все на их master
/ my origin/master
.
(я также поднял кучу новых тегов для версий ядра 5.4 и 5.5 и предстоящих 5.6.)
Короткая версия всего этого заключается в том, что вы можете выбрать здесь вывод git fetch
и вырезать и вставить два идентификатора ha sh в git log
или git rev-list --count
, чтобы посмотреть коммиты или посмотреть сколько их было.
В этом конкретном репозитории нет веток, к которым применяется git push --force
. Однако хранилище Git для самого Git делает. Моя копия этого экземпляра гораздо более свежая, поэтому я не могу показать фактический git fetch
вывод, но он будет выглядеть так:
+ old...new pu -> origin/pu (forced update)
Этот вывод имеет три разные вещи, кроме два идентификатора ha sh отличаются (и в данном случае фальшивыми):
- он имеет
+
спереди, что указывает на принудительное обновление; - it имеет три точки между двумя идентификаторами ha sh, указывающими на принудительное обновление; и
- оканчивается на
(forced update)
, указывая, что обновление было принудительным.
Нет разницы между этими тремя показателями. Просто очень важно , чтобы мой Git дал мне знать, что это было принудительное обновление, то есть теперь у меня есть некоторые коммиты в мое хранилище осталось, что они решили выбросить. Если я использую их pu
ветвь - мою origin/pu
ветку - каким-то образом, я должен знать об этом.
pu
(Предложенное обновление или PickUp) ветвь в Git - это ветка, которую все Git разработчики и другие сторонники согласились регулярно обновлять, перематывать и перестраивать. Коммиты в этой ветке могут быть заменены новыми и улучшенными или полностью отброшены; мы все согласны с тем, что будем иметь дело с этим, а не жаловаться на это.
4 Технически, идентификатор ha sh представляет собой битовую или байтовую строку. Git в настоящее время использует хэши SHA-1 длиной 160 битов, а затем представляет эти значения ha sh как шестнадцатеричные числа из 40 символов. Git постепенно продвигается к замене их на хэши SHA-2, длина которых составляет 256 бит.
5 Обратите внимание, что вы, возможно, добавили свои собственные коммиты для ваш репозиторий до этого момента. Вот почему Git не может использовать простые последовательные числа. Предположим, вы получили от них 1000 коммитов, пронумерованных от 1 до 1000. Затем вы делаете два ваших собственных коммита, номера 1001 и 1002. Теперь вы вызываете их Git, и у них есть три новых коммита, пронумерованных от 1001 до 1003. Что мы делаем? Что делать с этими перекрывающимися числами?
На самом деле можно сохранить некоторые локальные номера. Mercurial, который так же способен, как и Git, делает это. Местные номера иногда удобны, но в конце концов они не так удобны, как хотелось бы. Git просто не беспокоится о них.
6 Эта общность делает много предположений. Git меняет свою точность и делает это с минимальной информацией и делает это быстро. Если у вашего Git и их Git был более длинный разговор, который занимал бы большую пропускную способность сети, их Git мог бы иногда пропускать некоторые объекты, что занимало бы меньшую пропускную способность сети.
Почему вы нужна вторая Git команда
Когда git fetch
получает новые коммиты, они просто сидят там в вашей базе данных репозитория. Вы не можете видеть ничего из этого напрямую. Вы можете запустить на них git log
или git show
. Вы можете использовать идентификаторы commit ha sh, которые вы найдете с вашими именами удаленного отслеживания. Но в целом вам нужно сделать что-то с этими коммитами, чтобы получить файлы.
Если вы сделаете свои собственные коммиты, что-то , что вам нужно сделать сейчас - это обычно какая-то форма , включающая их работу в мою работу . Для этого используются две основные команды Git: git merge
, которые объединяют их работу с вашей, и git rebase
, копирующие ваши оригинальные коммиты для новых и улучшенных коммиты, с улучшением - по крайней мере, вы надеетесь, что это улучшение - в том, чтобы поместить эти коммиты после их новых коммитов, а не рядом с их.
Оба эти команды влияют на ваши ветви.
Fetch не делает: git fetch
получает вас новым коммитов , но ваши существующие коммиты совершенно не затрагиваются добавлением new те. Новые имеют разные большие уродливые идентификаторы ha sh. Каждый новый коммит имеет свой идентификатор ha sh, чем любой другой коммит. У комитетов нет небольших чисел; никто не сделает коммит # 3, так как коммит # 3 никогда не существует. Все, что делает git fetch
, это добавляет новые коммиты и обновляет ваши имена для удаленного слежения.
Но и git merge
, и git rebase
необходимо использовать ваше рабочее дерево . Ваше рабочее дерево или рабочее дерево (теперь Git в основном использует более длинный термин) - это то место, где Git извлекает снимки коммитов, так что вы можете видеть их и работать с ними / с ними - отсюда и название дерево работы: это то место, где вы выполняете свою работу. Операция слияния часто требует изменения вашего рабочего дерева. Операция rebase запускается повторно git cherry-picks
, каждая из которых часто требует изменения вашего рабочего дерева. И git merge
, и git cherry-pick
могут иметь конфликты слияния , которые вы должны разрешить: это означает, что Git не может понять это самостоятельно. В этом случае Git оставляет вам путаницу в вашем рабочем дереве, которую вы должны исправить.
В обоих случаях конечный результат слияния или перебазирования может изменить то, какой коммит является последним коммит в вашей ветке. Они всегда работают с вашей текущей веткой. Таким образом, эти две команды нуждаются в тщательном использовании, и всегда целесообразно сначала запустить git status
, чтобы убедиться, что ваша текущая ветвь (а) правильная ветвь и (б) готова к операции слияния или перебазирования.
Не стесняйтесь использовать git pull
, просто знайте, что он (1) запустит git fetch
, а затем (2) выполнит одну из этих других команд. У вас не будет возможности взглянуть и принять решение на основе вывода git fetch
: вы заранее приняли на себя обязательство git merge
или git rebase
. 7 Ничего не поделаешь в корне неправильно, но я предпочитаю разделять эти две операции.
(у меня есть псевдоним git mff
, который запускает git merge --ff-only
, что я часто использую после git fetch
. в сочетании с кратким взглядом на вывод выборки и текущее состояние обычно это то, что I хочет, и если оно не работает, , то Я хочу более внимательно рассмотреть все. )
7 Существуют некоторые необычные обстоятельства, когда вторая часть git pull
не является ни слиянием , ни rebase. Например, git pull
в абсолютно пустой репозиторий требует выполнения git checkout
вместо этого, поэтому он делает это. В древности Git (1,5 с чем-то или 1,6. что-то), это потеряло мне день или два работы, однажды, потому что это не было тщательно закодировано, а я еще не совершил. Это одна из причин, по которой я избегаю git pull
: это жгло меня не раз, причем этот конкретный случай - худший.