git clone --local
- Каждый репозиторий будет совместно использовать .git / objects с пустым репозиторием, но это означает, что .bare репозиторий mu sh будет доступен локально (поэтому это не может быть GitHub, верно?)
Не совсем верно, нет. Вы можете использовать это с любым локальным клоном, голым или нет. Но в целом, в тех случаях, когда это работает вообще, вам даже не нужно --local
: вы можете просто клонировать по локальному пути.
Например, предположим userA
, домашний каталог которого /home/userA
, клонирует репозиторий GitHub, делая полный и непонятный клон. Предположим далее, что userB
может прочитать из /home/userA
. Поэтому пользователь B может сделать:
git clone /home/userA/BigRepository
, чтобы создать ./BigRepository
. Если он сделает это в своем домашнем каталоге, он получит /home/userB/BigRepository
, который содержит все те же коммиты, что и клон userA
.
Поскольку Git будет делать жесткие ссылки, если пользователь А сейчас удаляет своего хранилища, он не восстанавливает свое пространство (поэтому, если действуют дисковые квоты, пользователь А не возвращает свою квоту). У пользователя B все еще есть ссылки на файлы, принадлежащие пользователю A. Все еще работает ; просто тот, кто сделал этот первый клон, «заплатил» за первоначальное хранилище для самого репозитория.
(пользователь B «платит» за свое собственное рабочее дерево . Он разделяет .git/objects
файлов , включая файлы пакета, которые создал пользователь A. Все эти файлы доступны только для чтения, независимо от того, совместно использует ли пользователь B файлы пользователя A или нет, поэтому тот факт, что пользователь B может ' t запись в эти файлы не важна.)
Единственный недостаток этого процесса в том, что пользователь B, вероятно, захочет изменить свой origin
URL, чтобы он указывал на репозиторий GitHub, а не клон пользователя А, и пока он этого не сделает, он не будет видеть тот же набор имен удаленного отслеживания (origin/*
имена), который видит пользователь А.
Пользователь C может повторите этот процесс с любым из предыдущих репозиториев.
git clone --depth <n>
- что уменьшит размер репо, но также уменьшит локальную историю до n объектов.
В основном да. Технически неверно с точки зрения числа n , хотя:
Будет --depth
означать, что репозитории будут иметь не более n коммитов, или проверяется только при клонировании, а затем хранилище может расти со временем?
Они не только растут со временем, число n не означает, что вы предлагаете. Это глубина , а не количество коммитов. Глубина в этом случае является техническим термином, относящимся к обходу графика.
Помните, что Git использует commit в качестве основной единицы хранения c. (Коммиты могут быть разбиты и далее, но для нашей цели они здесь единица.) Каждый коммит имеет уникальный идентификатор ha sh и может быть представлен в виде узла или вершины на графе. Каждый коммит также хранит идентификатор ha sh своего непосредственного коммита (ов) предшественника: они образуют односторонние ребра или дуги , связывающие узлы, и, следовательно, образуют остальную часть графа.
Мы можем нарисовать биты графика следующим образом:
... <-F <-G <-H
, где каждая буква обозначает коммит ha sh ID. Сохраненные идентификаторы ha sh в каждом коммите действуют как указатели на предыдущие коммиты. Чтобы легко найти конец этой цепочки, мы - или Git - устанавливаем sh имя ветви или какую-либо другую форму имени, которая указывает на last коммит в цепочке:
...--F--G--H <-- master
(где мы становимся ленивыми и рисуем соединительные дуги в виде линий по той простой причине, что никакой коммит никогда не может быть изменен, так что на самом деле это не имеет значения указывать путь, по которому идут стрелки - хотя в другое время важно помнить, что они изначально указывают назад , что заставляет Git работать в обратном направлении всегда.)
Теперь На графике с такими стрелками, направленными назад, могут быть разветвления и объединения:
o--o o--o--H <-- branch1
/ \ /
...--o--o--o---o--o--o--o--K <-- branch2
\ /
o--o--o--o
Когда мы пересекаем этот граф, мы начинаем с конца - в нормальных графах мы начинаем с начала, но Git работает в обратном направлении - как commit H
, как указано по имени branch1
. Если мы выберем --depth 3
, Git получит H
и два более ранних коммита и K
и два более ранних коммита:
o--o--H <-- branch1
/
<snip>--o--o--K <-- branch2
Наши --depth 3
получили шесть коммитов, потому что возвращаясь назад 3 с каждого конца получили нам эти коммиты из полного графа. Если мы go до --depth 4
получим:
o--o--H <-- branch1
/
<snip>--o--o--o--K <-- branch2
/
<snip>--o
Каждая из этих "отрывных" точек представляет собой мелкий трансплантат , где мы знаем, что были больше коммитов, но мы намеренно пропустили эти коммиты. Идентификаторы ha sh пропущенных коммитов записываются в .git/shallow
и Git знает, когда он посещает коммит, чьи родители перечислены в .git/shallow
, не пытаться найти родительские коммиты.
Аргумент --depth
выбирает точки отсечения. Это происходит во времена, когда git fetch
- git clone
представляет собой необычную обертку из шести частей, которая включает git fetch
в качестве пятого шага. Точки отсечения остаются там, где они есть, до тех пор, пока вы не запустите git fetch
с указанным аргументом c для углубления или дальнейшего углубления в хранилище. Новые коммиты добавляются обычным способом и делают граф глубже, включая любые git fetch
операции, которые выполняет любой из пользователей.
git clone --shallow-since
- насколько я понимаю, он будет работать аналогично в --depth
, но будет сохранять коммиты с указанного времени.
Да: это просто более полезный, а также менее запутанный способ установки точек «отсечки».
Вы имеете в виду --separate-git-dir
. В этом нет особого смысла: указанный вами каталог создается и заполняется операцией клонирования. В сочетании с любым из более ранних вариантов это поможет уменьшить необходимое пространство, но в противном случае оно просто отделяет рабочее дерево от самого хранилища.
При стандартной настройке само хранилище отображается в рабочее дерево в подкаталоге с именем .git
. С --separate-git-dir
, .git
все еще появляется в рабочем дереве, но на этот раз это файл , содержащий путь к хранилищу. В любом случае каждый пользователь оплачивает стоимость хранения независимо, если только не использует --local
, как подразумевается, путем клонирования репозитория другого пользователя.
Важно, чтобы у каждого пользователя был свой собственный фактический репозиторий
Если и когда пользователь A делает новый коммит, его Git должен записать один или несколько новых объектов в свой .git/objects
. (Так как фиксация всегда уникальна, операции необходимо, по крайней мере, написать этот объект. Возможно, ей также нужно написать несколько объектов дерева, и чтобы добраться до этой точки, Git, вероятно, пришлось создать несколько объектов BLOB-объектов.)
Между тем, если и когда пользователь B делает новый коммит, его Git должен записать один или несколько новых объектов в свой .git/objects
. Если пользователи A и B буквально совместно используют репозиторий Git , то A и B должны иметь разрешение на запись в файлы и каталоги других пользователей. Этот режим можно заставить работать, но у него есть дополнительный недостаток: каждый пользователь должен быть очень осторожным , чтобы случайно не наступить на других пользователей. Хотя основная часть репозитория, включая предлагаемые для совместного использования части .git/objects
, состоит из объектов, которые никогда не изменяются после записи, другие части, включая специальный файл .git/HEAD
, и многочисленные другие файлы, такие как данные заголовка ветви и reflogs, должен быть закрытым для каждого пользователя, или иначе - и эта альтернатива, как правило, неработоспособна - только один пользователь может выполнять какую-либо реальную работу в любое время.
В теории, git worktree add
можно использовать здесь
Однако он не предназначен для такого использования. Вы можете поэкспериментировать с ним, если хотите: добавить рабочее дерево для каждого пользователя, а затем дать этому пользователю разрешение на все файлы, связанные с этим пользователем (дополнительные файлы находятся в подкаталогах в пределах .git
).
предназначен для этого --reference
Что такое , предназначенное для решения этой проблемы, это опция --reference
. Используя --reference
, вы, как администратор компьютера, сначала создадите полный клон репозитория GitHub. Вы можете сделать это --bare
или нет - это не очень важно - но вы можете захотеть сделать его клоном --mirror
, чтобы он получал каждый реф и мог легче обновляться. (Я немного поэкспериментировал с этим на предыдущей работе, и здесь есть некоторые проблемы, которые усложняют его обновление, так что это может быть не так полезно, как вы думаете вначале.)
Once this "эталонный клон "существует, каждый пользователь может сделать:
git clone --reference <path> <github-url>
Их Git свяжутся с Git на GitHub и получат от него информацию, необходимую для создания полного клона. Но затем, вместо того, чтобы на самом деле сделать полный клон, они проверяют эталонный клон, чтобы увидеть, есть ли у него уже нужные объекты. Всякий раз, когда и где эталонный клон уже имеет эти объекты, их Git будут просто использовать эти существующие объекты в этом существующем эталонном клоне.
Что это означает, что сам git clone
идет очень быстро и почти не использует дополнительное дисковое пространство. Для создания исходного эталонного клона ~ 3 ГБ может потребоваться несколько минут или даже несколько часов, но когда один из пользователей выполняет эту операцию git clone --reference
, он должен завершиться sh в секундах. Более того, он работает «чисто» в том смысле, что если ему нужны новые объекты от GitHub, они просто получают их из GitHub как обычно. Поскольку никакой коммит - никакой Git объект любого вида, действительно - никогда не может быть изменен , эталонный клон просто служит для предоставления всех объектов, которые вы изначально поместили в него. Новые объекты постепенно расширяют репозиторий каждого пользователя.
(В будущем вы можете обновить эталонный клон. Отдельные пользователи могут затем повторно клонировать, чтобы уменьшить использование своего диска. Сложность заключается в том, что вы должны сделать убедитесь, что ни один объект, ни файл пакета не исчезнут из ссылочного клона между временем его обновления и временем их повторного клонирования. Вместо этого вы можете просто создать новый ссылочный клон, подождать, пока все пользователи чтобы избежать этой хитрости, повторно клонировали новый клон ссылки, а затем удалите исходную ссылку.)