Ошибка при настройке репо git на общем диске - PullRequest
0 голосов
/ 21 апреля 2020

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

Я на Windows 10 Pro, с сетевым диском, который я называю Y. Я помещу эти репозитории в каталог с умным именем git. Я нашел инструкции для этого из командной строки DOS:

Y:
cd \git\
git init --bare myrepo.git

Затем из места, где находится код, я хочу добавить его в репозиторий:

C:
cd \files\programming\workspaces\project1
git remote add origin y:\git\myrepo.git

Когда я выполняю последнюю строку, я получаю сообщение:

fatal: not a git repository (or any of the parent directories): .git

Я пробовал это с косой чертой и обратной косой чертой; Я удалил каталог, который я создал с помощью команды git, и сделал это заново (на случай, если я что-то забыл), но все равно получаю тот же результат. Что я делаю неправильно?

Ответы [ 2 ]

2 голосов
/ 21 апреля 2020

Я поставлю это как отдельный ответ, с точки зрения настройки второго (и --bare) хранилища. Вы уже сделали это на Y:. Вы упоминаете, что это общий / доступный по сети диск; иногда это нормально, в зависимости от того, как обстоят дела с блокировкой файлов на общих дисках. Существуют подробности ОС c, спецификация файловой системы c и спецификация сети c, которые необходимо учитывать. Давайте просто предположим, что они в порядке, и / или что вы и ваши коллеги позаботитесь о том, кто пишет на диск Y:. В любом случае, сделав:

cd Y:\git\
git init --bare myrepo.git

, теперь у вас есть второй репозиторий (сделан первым, но порядок создания не имеет большого значения). Тем временем вы теперь делаете:

cd C:\files\programming\workspaces\project1
git init

, который создает .git в C:\files\programming\workspaces\project1. Теперь вы можете добавить remote , который является просто именем для другого Git хранилища, в котором вы храните URL другого Git хранилища:

git remote add origin file://Y:/git/myrepo.git

Теперь, когда есть .git (хранилище) в C:\files\programming\workspaces\project1, это git remote add должно работать. Имя origin просто условно: вы можете использовать любое имя, которое вам нравится, но origin - это имя, которое git clone создает, когда вы используете git clone для создания локального (C: область) хранилища.

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

Теперь вы готовы иметь свой локальный репозиторий - тот, что в C:\files\programming\workspaces\project1\.git - позвоните на секунду Git в file://Y:/.... Но нет смысла соединять любое из этих двух хранилищ, пока хотя бы у одного из них не будет некоторых коммитов, потому что коммиты являются основной валютой обмена между двумя Git хранилищами. Таким образом, в любое время до или после git remote add вы захотите сделать хотя бы один начальный коммит, что приведет к появлению имени ветви master.

Как только вы получите коммит, или некоторые коммиты, вы можете выполнить:

git push origin master

Команда git push соединяет ваш Git - репозиторий, в котором вы сейчас находитесь - с другим Git. Имя origin здесь - это имя пульта, как обычно устанавливается git clone, но вашим git remote add в данном конкретном случае. Последний аргумент master - это то, что Git называет refspe c.

Refspecs немного сложнее. Они состоят из двух частей, разделенных двоеточием :. Этот конкретный refspe c, master, отсутствует двоеточие. Для git push это означает: используйте одно и то же имя с обеих сторон . Так что это действительно сокращение:

git push origin master:master

Имя слева от двоеточия обычно представляет собой имя ветви в вашем хранилище. Имя в правой части двоеточия - это имя соответствующей ветви в их хранилище - другой Git.

Ваш Git теперь будет вызывать другой Git, часто более сетевое соединение (ssh:// или git:// или http:// или https:// URL). В этом случае ваш Git напрямую работает со вторым репозиторием Git, но вы можете просто думать об этом как о выделении второй команды Git, которая действует как получатель для другого репозитория (потому что это действительно так) .

Ваш Git теперь предлагает коммиты для других Git по их идентификаторам ha sh. Они проверяют идентификатор ha sh и регистрируют свою базу данных коммитов-и-других- Git -объектов, чтобы узнать, есть ли у них идентификаторы ha sh. Ваш Git хочет знать: я должен дать вам, другой Git, этот? Или он у вас уже есть? На данный момент их база данных пуста, поэтому ответ всегда: У меня его нет - дай мне! Ваш Git теперь упаковывает их, сжимая их для передачи по сети, и отправляет их через. Они устанавливают эти коммиты в своей базе данных.

В конце этого процесса ваш Git отправляет Git вежливый запрос в форме: Пожалуйста, если это Хорошо, установите ваш master сейчас так, чтобы он указывал на тот же коммит, на который указывает мой master. Если они принимают - и здесь, они будут - у них теперь есть их master, указывающие на последний коммит в цепочке коммитов, который заканчивается коммитом, который находится в вашем хранилище, которое ваш Git находит через ваше имя master.

Если это звучит сложно, то это потому, что это так: вы, а они нет поделиться названиями ветвей вообще, если только вы и не захотите. Но вы и они делаете делитесь фиксируете объекты с их уникальными идентификаторами ha sh.

Получение (и клонирование) не совсем симметрично c, но я У меня нет времени для этого ответа.

0 голосов
/ 21 апреля 2020

Очевидно, C:\files\programming\workspaces\project1 не является репозиторием Git.

Это правда, что Y:\git\myrepo.git - это репозиторий Git (при условии, что ранее работал git init). Но C:\files\programming\workspaces\project1 нет. Вам нужно будет создать второй репозиторий Git. 1 Например, вы можете git clone пустой репозиторий в Y:\git\myrepo.git (хотя клонирование полностью пустого репозитория имеет некоторые странные побочные эффекты и обычно это не правильный способ запуска).

В общем случае Git работает так:

  • Вы клонируете целый существующий репозиторий: каждый коммит, который сохраняет каждая версия каждого файла теперь копируется в каталог .git здесь.

    Git - действительно все об этих коммитах. Каждый коммит имеет полный и полный снимок каждого файла, сохраненный в специальном формате только для чтения, Git, а также некоторую дополнительную информацию, например, кто сделал коммит, когда и почему. Эти коммиты действуют как архивы: каждый раз, когда кто-то запускает git commit, Git в архиве все . 2 Теперь у вас есть копия все , в этом специальном формат Achival, который может использовать только Git.

    Каждый коммит имеет свой уникальный идентификатор ha sh. Никакие две коммиты никогда не могут делиться ID. По этой причине и из-за того факта, что каждый Git в мире должен предоставить каждому уникальному идентификатору ha sh, эти идентификаторы должны быть очень большими, уродливыми и случайными. Все Гиты повсюду делятся га sh идентификаторами для всех своих коммитов, так что они могут поделиться своими коммитами по ID, позже. Вы можете соединить любые два Gits друг с другом, и они могут получить коммиты друг друга, просто используя эти идентификаторы ha sh.

    Поскольку эти идентификаторы ha sh такие большие и уродливые, люди не могут получить они правы. К счастью, мы не должны; мы увидим это чуть позже.

  • Затем - это фактически встроено, как последний шаг из git clone, который вы только что сделали - у вас есть Git выберите некоторый коммит. Этот выбранный коммит становится текущим коммитом .

    Обычно вы выбираете коммит, выбирая имя ветви , и в этом случае это имя становится текущим именем ветви , т. Е. Эти два действия спарены: выбор ветви master в качестве текущей ветви выбирает последний коммит в этой ветви в качестве текущего коммита.

    (есть дополнительная сложность при выполнении этого начального git clone, опять же, но мы пока пропустим его.)

  • Git сейчас извлекает все файлы из выбранного коммита, в рабочую область. В этой рабочей области у вас есть обычные файлы, которые вы можете использовать со всеми обычными программами на вашем компьютере. Это ваши файлы, с которыми вы будете работать sh: они вовсе не являются копиями Git. Git просто извлек все из коммита, чтобы сделать эти копии доступными.

Как только у вас есть все рабочие копии файлов, хранящиеся в этой рабочей области , который мы называем рабочим деревом или рабочим деревом , вы можете работать с ними. Вот почему это ваше рабочее дерево: потому что вы на самом деле можете выполнить некоторую работу.

Поработав над кучей файлов, вы можете сохранить новый сохраненный за все время архивный снимок. Вы можете подумать, что можете просто запустить git commit, а Git сохранит все ваши файлы. Другие системы контроля версий работают таким образом, но Git - нет. Git содержит в секретном файле 3 сохраненные все файлы, полученные из текущего коммита. Эти файлы представлены в специальном Git -только замороженном формате, но в отличие от копий файлов, которые находятся в коммитах, на самом деле они не заморожены . Вы можете заменить их, или полностью удалить некоторые файлы, или вставить новые.

Git называет эту специальную дополнительную область index , или промежуточная область , а иногда - редко в наши дни - кеш . Эти три имени для этой единственной вещи отражают ее центральные и множественные роли в Git, или, возможно, есть три имени, потому что оригинальное имя, «индекс», просто ужасно. :-) Но в любом случае вам нужно знать об индексе.

По существу - и не упоминая некоторые другие его роли - что представляет собой индекс и что он представляет собой next , обязывающее вас сделаю. То есть он содержит в специальном формате Git -specifi c некоторую информацию о вашем текущем рабочем дереве, но, что более важно, копию каждого файла, которая будет go в следующем коммите. 4

Обновив файлы рабочего дерева, вам необходимо скопировать эти файлы обратно в индекс Git, что вы делаете с git add:

git add file1 folder/file2

например. 5 Это копирует эти два файла из вашего рабочего дерева в указатель, превращая копии в специальный Git формат, готовый go в следующий коммит. Другими словами, эти файлы теперь подготовлены для коммита , отсюда и другое название индекса - «область подготовки». На самом деле они еще не совершены , но они готовы к go. (Они были готовы к go и раньше, но раньше они соответствовали копии текущего коммита!)

На этом этапе выполнение git commit создает новый коммит из любых файлов в индексе прямо сейчас . Этот новый коммит получает ваше имя и адрес электронной почты как автора и коммиттера, а «сейчас» - текущую дату и время, сообщаемое вашей ОС - как метки времени. Вы должны предоставить лог-сообщение с указанием причины того, что вы сделали коммит: краткое изложение почему вы делаете все, что делаете. 6

Команда git commit упаковывает всю эту информацию - кто, когда, почему и т. Д. - вместе с необработанным идентификатором ha sh текущего текущего коммита и создает новый коммит из это плюс снимок, который он делает, используя файлы, которые уже имеют правильный формат в индексе Git. Теперь, когда новый коммит сделан, он становится текущим коммитом. Теперь все вернулось к тому, что было, когда вы запустили git checkout: и индекс, и текущий коммит содержат одинаковый набор файлов в формате замороженного архива, готовый к go в новый коммит.

Обратите внимание, что никаких изменений коммита не было. Фактически, ни один из существующих Git commit не может когда-либо измениться. Все коммиты заморожены на все время, только для чтения. Они продолжают существовать до тех пор, пока вы и Git сможете найти их - обычно навсегда, но вы можете договориться о "потере" одного, если вы сделали тот, который вам не нравится.

Способ Git находит коммитов важен и немного сложен. Однако, как только вы это освоите, на самом деле все будет очень просто.


1 Это может быть единственный репозиторий, который вам нужен: непонятно, зачем вам нужен пустой и во-первых, в Y:\git\myrepo.git.

2 Точнее, Git заархивировал все, что было сказано, в архив, как мы увидим через мгновение.

3 Это не совсем секрет вообще, но вы не можете увидеть это очень хорошо: оно спрятано в специально отформатированном файле в .git с именем index (и, возможно, и с других мест, но все они начинаются с индексного файла; индексный файл содержит записи, и некоторые из них могут содержать другие файлы).

4 Технически, то, что находится в индексе в этих записях кэша , это путь к файлу, режим и внутренний Git блоб ха sh ID . Также имеется номер промежуточного слота , который действительно используется только для слияния. Идентификатор ha sh означает, что вместо хранения фактической копии каждого файла индекс просто содержит запись объекта блоба, отформатированного Git. Но если вы не начнете использовать git ls-files --stage и git update-index напрямую, вам не нужно знать об этом: вы можете просто думать об индексе как о хранении копии каждого файла.

5 Вы можете использовать либо forward sla sh как этот, либо обратную косую черту; обе работают. Я не использую Windows, и всегда использую forward sla sh, и несколько раз, когда я был вынужден кратко использовать Windows, я всегда называю свои файлы там с косой чертой. (Это в основном работает, за исключением нескольких команд, которые настаивают на том, что они переключают параметры. При работе с Git и его экосистемой backsla sh имеет тенденцию путать некоторые другие программы: \b, например, может представлять Backspace и \t вкладка, поэтому попытка присвоить файлу имя .\buttons\toggle может дать сбой, и в результате вы получите файл с именем .^Huttons^Toggle или чем-то еще.)

6 Git может легко показать , что вы сделали позже, но Git даже не подозревает, что это было, например, чтобы исправить ошибку # 12345 или проблему # 97, или что бы то ни было, тем более как ошибка или проблема может быть описана. Это сообщение журнала - это ваша возможность объяснить, например, что такое ошибка, где ее найти в системе сообщений об ошибках, что вы обнаружили во время исследования ошибки, и что-нибудь еще, что может быть полезно вам или кому-то еще, глядя на этот коммит позже.


Имена ветвей позволяют Git найти коммиты для вас

Имя ветки, подобное master, в Git, на самом деле просто содержит one га sh ID.

Это все, что нужно сделать. Ранее мы упоминали, что всякий раз, когда вы Git делаете новый коммит, новый коммит сохраняет необработанный га sh ID текущего коммита.

Предположим у вас есть Git репозиторий с одним коммитом. Этот коммит имеет какой-то большой уродливый идентификатор sh, но мы просто назовем его A для краткости:

A

В репозитории только один коммит. Этот коммит имеет много файлов, но это всего лишь один коммит. Его легко найти: это коммит . Давайте теперь добавим второй коммит, получив этот коммит с именем master - мы поместим имя в одно мгновение.

Мы изменим некоторые файлы рабочего дерева, git add их, и запустите git commit и укажите причину для фиксации в сообщении журнала. Git создает новый коммит из всех файлов в индексе, плюс обычные метаданные, в том числе ha sh ID коммита A. Давайте назовем новый коммит B и нарисуем его сейчас:

A <-B

B содержит идентификатор ha sh старого коммита. Мы говорим, что B указывает на A.

Git записывает новый коммит ха sh ID в имя master, поэтому давайте нарисуем имя master, указывающее на B сейчас:

A--B   <-- master

Я уже стал ленивым (нарочно): это B, которое указывает на A, а не наоборот. Но стрелка, выходящая из B, не может измениться, потому что никакая часть любого коммита не может измениться. Это стрелка, выходящая из master, которая меняется. Мы называем commit A родителем B, а B дочерним A.

Текущей ветвью теперь является master, а текущим коммитом - B. Давайте сделаем новый коммит обычным способом:

A--B--C   <-- master

Новый коммит C указывает на B, что указывает на A. Так что B может быть потомком A, но также является родителем C.

(Куда указывает A? Ответ: нигде. Коммит A немного немного особенный. Будучи самым первым коммитом, он не может указывать на какой-либо более ранний коммит. Так что это просто не так. Создание первого коммита в репозитории является чем-то особенным; создает имя ветви тоже! Имя master не может существовать, пока не существует какой-либо коммит, поэтому создание коммита A создает все.)

(я продолжаю говорить ребенок , а не ребенок . Это потому, что мы можем go вернуться и добавить еще детей позже. Когда-то сделанные комитеты заморожены на все времена, поэтому дети точно знают, кто их родители Есть, но родители могут приобрести новых детей, когда-нибудь, в будущем. Когда создается новый коммит, у него никогда не бывает потомков , но . Поэтому родители никогда не знают, кто их дети. Вот почему Git работает задом наперед!)

Обратите внимание, что все, что нам нужно, это Git для хранения необработанного (и случайного вида) га sh идентификатора последнего коммита во имя master. Мы можем вспомнить имя master, а Git помнит идентификатор ha sh для нас. Добавление нового коммита состоит из:

  • , удостоверяющих, что текущее имя ветви равно master (git checkout master при необходимости)
  • , чтобы текущий commit - это C
  • , так что a123456... index содержит Git полных правильных копий файлов и нашего рабочего дерева есть файлы, которые мы хотим
  • , чтобы мы могли изменить файлы рабочего дерева на месте, используя все обычные компьютерные инструменты
  • , чтобы мы могли git add обновленные файлы, чтобы сделать Git скопируйте их обратно в индекс
  • , чтобы мы могли git commit сделать новый коммит D

, который изменит наш рисунок на:

A--B--C--D   <-- master

Все эти новые коммиты go в нашем хранилище . Сам репозиторий состоит в основном из двух больших баз данных:

  • коммитов и других внутренних Git объектов, адресованных идентификаторами ha sh;
  • и меньшего размера name-to-ha sh -ID таблица, которая говорит что-то вроде имя ветки master означает фиксацию *1338* или что-либо еще.

Весь репозиторий находится в каталоге / папке .git под верхним уровнем нашего рабочего дерева. Имена ветвей находят последний коммит, а эти коммиты находят более ранние коммиты. Git просто идет назад, от последнего коммита обратно к первому, один коммит за раз. Git знает, что у него закончились коммиты, чтобы пройти назад, когда он достигает root коммитов, таких как коммит A, у которого нет родителя.

Существует много больше, чем это, начиная с того факта, что вы можете добавить больше имен ветвей: например,

A--B--C--D   <-- master, dev

, перемещать имена ветвей и т. д., и мы даже не затронули идею подключения этого Git хранилища в C:\files\programming\workspaces\project1 к другому Git хранилищу в Y:\git\myrepo.git или на другом компьютере или еще где-либо. Вот где все усложняется. Вот для чего git remote: remote - это имя, которое вы используете в вашем Git, чтобы запомнить URL для какого-либо другого Git хранилища.

Если вам пока не нужно использовать пульты, не делайте этого; это достаточно для начала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...