Где git хранит файлы
Я только начал изучать Git и для этого я начал читать книга сообщества Git, и в этой книге они говорят, что SVN и CVS хранят разницу между файлами и что git хранит снимок всех файлов.
но я действительно не понял, что они подразумевают под снимком. Действительно ли git делает копию всех файлов в каждом коммите, потому что это то, что я понял из их объяснения.
PS: Если у кого-то есть лучший источник для изучения git, я бы ценить это.
git включает для каждого фиксации полную копию всех файлов, за исключением того, что для содержимого, уже присутствующего в репозитории Git, снимок просто укажет на указанное содержимое, а не дублирует его.
Это также означает, что несколько файлов с одинаковым содержимым хранятся только один раз.
таким образом, снимок в основном является фиксацией, ссылаясь на контент структуры каталогов.
некоторые хорошие ссылки являются:
вы говорите Git, что хотите сохранить снимок вашего проекта с помощью команды git commit, и он в основном записывает манифест того, как выглядят все файлы в вашем проекте в этот момент
Лаборатория 12 показано, как получить предыдущий снимки
на progit book более подробное описание снимка:
основная разница между Git и любыми другими VCS (Subversion и друзья включены) - это то, как Git думает о своих данных.
Концептуально большинство других систем хранят информацию в виде списка изменений на основе файлов. Эти системы (CVS, Subversion, Perforce, Bazaar и т. д.) считают информацию, которую они хранят, набором файлов и изменениями, внесенными в каждый файл с течением времени
Git не хранит свои данные в таком виде. Вместо этого, git считает хранимые данные набором слепков небольшой файловая система.
Каждый раз, когда вы фиксируете или сохраняете состояние своего проекта в Git, он в основном делает снимок того, как выглядят все ваши файлы в данный момент, и сохраняет ссылку на этот снимок.
Чтобы быть эффективным, если файлы не изменились, Git не сохраняет файл снова-просто ссылку на предыдущий идентичный файл, который он уже сохранил.
Мерзавец думает о своих данных, как показано ниже:
Это важное различие между Git и почти всеми другими VCSs. Это заставляет Git пересмотреть почти все аспекты контроля версий, которые большинство других систем скопировали с предыдущего поколения. Это делает Git больше похожим на мини-файловую систему с невероятно мощными инструментами, построенными поверх нее, а не просто VCS.
пока это верно и важно на на концептуальном уровне это неверно на уровне хранения.
Git использует дельты для хранения.
Не только это, но и более эффективно, чем любая другая система. Потому что он не сохраняет историю каждого файла,, когда он хочет сделать сжатие, он принимает каждый blob, выбирает некоторые blobs, которые, вероятно, будут похожи (используя эвристику, которая включает в себя самое близкое приближение предыдущей версии и некоторых других), пытается сгенерировать дельты и выбирает маленький. Таким образом, он может (часто, зависит от эвристики) воспользоваться другими подобными файлами или более старыми версиями, которые более похожи, чем предыдущие. Параметр "pack window"позволяет торговать для качества Дельта-сжатия. По умолчанию (10) обычно дает достойные результаты, но когда пространство ограничено или для ускорения сетевых передач, git gc --aggressive использует значение 250, что делает его очень медленным, но обеспечивает дополнительное сжатие для исторических данных.
Git логически сохраняет каждый файл под своим SHA1. Это означает, что если у вас есть два файла с точно таким же содержимым в репозитории (или при переименовании файла), сохраняется только одна копия.
но это также означает, что при изменении небольшой части файла и фиксации сохраняется другая копия файла. Способ git решает это с помощью файлов пакета. Время от времени все "свободные" файлы (на самом деле, не только файлы ,но и объекты, содержащие информацию о фиксации и каталоге) из РЕПО собираются и сжимаются в файл pack. Файл пакета сжимается с помощью zlib. И подобные файлы также delta-compressed.
тот же формат также используется при вытягивании или нажатии (по крайней мере, с некоторыми протоколами), поэтому эти файлы не нужно снова сжимать.
результатом этого является то, что репозиторий git, содержащий всю несжатую рабочую копию, несжатые последние файлы и сжатые старые файлы обычно относительно малы, меньше чем в два раза больше рабочего экземпляра. И это означает, что он меньше, чем SVN repo с теми же файлами, хотя SVN не хранит историю локально.
ответы выше довольно голова, но я хотел бы добавить еще одну маленькую крошечную концепцию, известную как Дельта-кодирование. Эффективность сохраняется до тех пор, пока не будет записан файл пакета. Свободные объекты записываются в сжатом, но не Дельта-формате во время каждой фиксации.
Материал ориентирован прежде всего на читателей, умеющих работать с Git на уровне обычного пользователя и знающих основные концепции работы с ним. Возможно, статья не будет содержать ничего нового для разработчиков систем контроля версий, поддерживающих легкое создание веток и их надежное слияние. Вся информация взята из открытых источников, в том числе из исходных текстов Git (2d242fb3fc19fc9ba046accdd9210be8b9913f64).
Хранение данных: объекты
В Git единицей хранения данных является объект (англ. object), который однозначно определяется 40-символьным хешем sha1. В объектах Git хранит почти всё: коммиты, содержимое файлов, их иерархию. Сначала объекты представляют из себя обычные файлы в папке .git/objects, а после git gc упаковываются в .pack-файлы, о которых будет рассказано чуть ниже. Для экономии дискового пространства содержимое всех объектов дополнительно сжимается с помощью zlib.
Узнать тип объекта можно, набрав
Также хранение объектов целиком позволяет делать надежное слияние веток с разрешением конфликтов. Но об этом чуть позже.
Tree (иерархия ФС)
объекте типа дерево (англ. tree) хранится список записей, который соответствует иерархии файловой системы. Одна запись представляет из себя следующее:
Права файла в Git могут иметь лишь очень ограниченный набор значений:
040000 — директория;
100644 — обычный файл;
100755 — файл с правами исполнения;
120000 — символическая ссылка.
Тип объекта — это BLOB или tree, для файла и директории соответственно. То есть в объекте типа tree для корневой директории хранится вся иерархия файловой системы, поскольку внутри одного дерева могут быть ссылки на другие деревья.
Commit
В Git один коммит (англ. сommit) представляет из себя ссылку на объект tree, соответствующий корневой директории, и ссылку на родительский коммит (кроме самого первого коммита в репозитории). Также в коммите есть информация об авторе и UNIX timestamp от времени создания.
Если коммит является простым merge ( git merge <имя ветки> ), то у него будет 2 родителя: текущий HEAD и коммит, на который указывает <имя ветки> . Git также поддерживает стратегию слияния «осьминог» (англ. octopus), при котором он может выполнять merge более двух веток. Для таких коммитов количество родителей будет больше двух.
Pack-файлы
«. It's worth explaining (you are probably aware of it, but
let me go through the basics anyway) how git delta-chains work, and how
they are so different from most other systems.
In other SCM's, a delta-chain is generally fixed. It might be "forwards"
or "backwards", and it might evolve a bit as you work with the repository,
but generally it's a chain of changes to a single file represented as some
kind of single SCM entity. In CVS, it's obviously the *,v file, and a lot
of other systems do rather similar things.
Git also does delta-chains, but it does them a lot more "loosely". There
is no fixed entity. Delta's are generated against any random other version
that git deems to be a good delta candidate (with various fairly
successful heursitics), and there are absolutely no hard grouping rules.
This is generally a very good thing. It's good for various conceptual
reasons (ie git internally never really even needs to care about the whole
revision chain - it doesn't really think in terms of deltas at all), but
it's also great because getting rid of the inflexible delta rules means
that git doesn't have any problems at all with merging two files together,
for example - there simply are no arbitrary *,v "revision files" that have
some hidden meaning.
It also means that the choice of deltas is a much more open-ended
question. If you limit the delta chain to just one file, you really don't
have a lot of choices on what to do about deltas, but in git, it really
can be a totally different issue».
Если кратко, то в pack-файлах объекты группируются по схожести (например, тип и размер), после чего они сохраняются в виде «цепочек». Первый элемент цепочки представляет из себя самую новую версию объекта, а следующий за ним являются диффом к предыдущему. Самые новые версии объекта считаются наиболее запрашиваемыми, поэтому они хранятся выше в цепочке.
Таким образом, Git всё же хранит диффы, но только на уровне непосредственного хранения данных. С точки зрения любого API уровнем выше, Git оперирует объектами целиком, что позволяет реализовывать различные стратегии слияния и легко разрешать конфликты.
Хранение истории
В Git нет отдельного хранилища истории. Всю историю можно развернуть, но лишь пройдя по ссылкам на родителя из нужного вам коммита. Если необходимо просмотреть историю только по одному файлу (или по поддиректории), Git всё равно должен проделать то же самое, но он будет возвращать отфильтрованные результаты. Стоит иметь это ввиду, когда вы делаете интеграцию с Git, и не заставлять Git делать полный просмотр истории на каждый файл.
К тому же, как вы могли заметить, Git не хранит информацию о переименовании файлов. Если нужно понять, переименован файл или нет, Git производит анализ содержимого хранящихся у него объектов и с некоторым (настраиваемым) допуском считает, что файл был переименован.
Merge: трехстороннее слияние (стратегия resolve)
Если нужно выполнить слияние двух веток, то git по умолчанию использует стратегию recursive, но о ней чуть позже. До того, как появилась эта стратегия, использовалась стратегия resolve, которая представляет из себя трехстороннее слияние. Для того, чтобы выполнить такое слияние, нужно иметь 3 версии: общий родитель, версия из одной ветки и версия из другой ветки. Если вы выполняете слияние файлов, то такое трехсторонее слияние может выполняться утилитой diff3, которая входит в стандартный пакет diffutils. Эта скромная и редко упоминаемая утилита, так или иначе, делает всю «грязную работу» по слиянию в большинстве существующих систем контроля версий, включая RCS, CVS, SVN и, конечно же, Git.
Помимо использования аналога diff3 (конкретная реализация, используемая в Git — это LibXDiff), Git также «на лету» вычисляет переименования файлов и использует эту информацию для слияния tree-объектов. Слияние иерархий директорий не представляет из себя ничего принципиально сложного по сравнению с тем, чтобы выполнить слияние файлов, но порождает очень много различных видов конфликтов.
Небольшая иллюстрация того, как Git выполняет трехстороннее слияние в простом случае (взято из man git-merge):
Предположим, у нас есть такая история и текущая ветка — master:
Тем не менее разработка в ветках topic и master может быть продолжена, и тогда слияние уже не будет выглядеть так просто: у нас может быть больше, чем один коммит, который подходит под определение «общий предок»:
Если мы будем использовать стратегию resolve, то будет выбран самый старый общий предок (коммит E). Если в результате выполнения merge были конфликты, разрешённые в коммите H, нам всё равно нужно будет разрешать их ещё раз.
Для выполнения слияния с помощью стратегии resolve Git возьмет коммит E в качестве общего предка и коммиты M и P в качестве двух новых версий. Если в коммите C был конфликт, то конфликтующие изменения можно откатить с помощью git revert (например, это проделано в коммите K), тогда конечное состояние M уже не будет содержать в себе конфликта, и при слиянии конфликтов тоже не будет.
Merge made by the 'recursive' strategy
Представим себе такую историю:
- cоставляем список всех общих предков, начиная с самого свежего;
- берем за текущий коммит самого первого предка;
- выполняем слияние текущего коммита со следующим предком и получаем виртуальный коммит, который берем за текущий;
- выполняем предыдущую операцию до тех пор, пока не закончится список общих предков.
Результатом выполнения этой операции будет виртуальный коммит, который представляет из себя «смерженное» состояние всех общих предков в правильном порядке — разрешение конфликтов тоже попадет в этот коммит, причем более свежие коммиты будут иметь приоритет. Когда мы получили общего предка, выполняется трехсторонее слияние, описанное выше.
Выдержка из merge-recursive.c:
Низкоуровневые команды Git
Если вы работали какое-то время с Git, то вы наверняка знаете о командах checkout, branch, pull, push, rebase, commit и некоторых других. Но изначально Git создавался не как полноценная система контроля версий, а как фреймворк для её создания. Поэтому в Git есть очень богатый набор встроенных команд, которые работают на низком уровне. Приведем некоторые из них, весьма полезные, на наш взгляд:
git rev-parse <revision>
Эта команда является очень простой: она возвращает хеш коммита для указанной ревизии. Например, git rev-parse HEAD вернет хеш коммита, на который указывает HEAD.
git rev-list <commit>.
Команда выводит список хешей коммитов по указанному запросу и может использоваться как более быстрая альтернатива git log . Например, git rev-list branch ^origin/branch ^origin/master выведет все коммиты из ветки branch, которые ещё не были запушены (при условии, что origin/branch и origin/master являются свежими, например перед этим был сделан git fetch ).
Подводные камни: Что касается запросов вида branch ^other_branch, Git может неправильно вывести результаты, если у коммитов стоит неправильное время. Например, в выводе могут быть пропущены коммиты, которые «произошли в будущем» по сравнению с merge ветки.
git diff-index
Показывает разницу между рабочей копией и индексом (.git/index). В индексе Git хранит кеш lstat() от всех файлов, о которых он знает.
git cat-file <object>
Эта команда уже встречалась в статье, но её всё же стоит упомянуть ещё раз. Она позволяет получить содержимое коммита и любого другого объекта Git.
git ls-tree <object>
Выводит содержимое tree-объекта в приемлемом виде.
git ls-remote <repository>
Выводит информацию о ветках и тегах (вместе с хешами коммитов) из указанного удаленного репозитория.
GIT_SSH
Если вы писали скрипты, которые делают git pull, то скорее всего сталкивались с тем, что SSH запрашивает подтверждение «аутентичности» удаленного репозитория, причём делает это интерактивно. Решение этой проблемы не столь изящное, потому что GIT_SSH должен быть путем к исполняемому файлу (а не опции SSH):
Заключение
Как можно было увидеть, Git позволяет действительно хорошо и надежно работать с ветками, в том числе корректно обрабатывать ситуации, когда у двух веток есть более одного общего предка. Если только вашей целью не является написание своей системы контроля версий, мы бы рекомендовали использовать результаты работы Git, а не пытаться воспроизвести его алгоритм слияния.
Надеемся, данный материал оказался интересным для вас и позволил понять, почему Git работает именно так, а не иначе. Полагаем, что статья будет также полезной для разработчиков различных интерфейсов к Git, приводя к более глубокому пониманию того, что же происходит «под капотом».
Материал ориентирован прежде всего на читателей, умеющих работать с Git на уровне обычного пользователя и знающих основные концепции работы с ним. Возможно, статья не будет содержать ничего нового для разработчиков систем контроля версий, поддерживающих легкое создание веток и их надежное слияние. Вся информация взята из открытых источников, в том числе из исходных текстов Git (2d242fb3fc19fc9ba046accdd9210be8b9913f64).
Хранение данных: объекты
В Git единицей хранения данных является объект (англ. object), который однозначно определяется 40-символьным хешем sha1. В объектах Git хранит почти всё: коммиты, содержимое файлов, их иерархию. Сначала объекты представляют из себя обычные файлы в папке .git/objects, а после git gc упаковываются в .pack-файлы, о которых будет рассказано чуть ниже. Для экономии дискового пространства содержимое всех объектов дополнительно сжимается с помощью zlib.
Узнать тип объекта можно, набрав
Также хранение объектов целиком позволяет делать надежное слияние веток с разрешением конфликтов. Но об этом чуть позже.
Tree (иерархия ФС)
объекте типа дерево (англ. tree) хранится список записей, который соответствует иерархии файловой системы. Одна запись представляет из себя следующее:
Права файла в Git могут иметь лишь очень ограниченный набор значений:
040000 — директория;
100644 — обычный файл;
100755 — файл с правами исполнения;
120000 — символическая ссылка.
Тип объекта — это BLOB или tree, для файла и директории соответственно. То есть в объекте типа tree для корневой директории хранится вся иерархия файловой системы, поскольку внутри одного дерева могут быть ссылки на другие деревья.
Commit
В Git один коммит (англ. сommit) представляет из себя ссылку на объект tree, соответствующий корневой директории, и ссылку на родительский коммит (кроме самого первого коммита в репозитории). Также в коммите есть информация об авторе и UNIX timestamp от времени создания.
Если коммит является простым merge ( git merge <имя ветки> ), то у него будет 2 родителя: текущий HEAD и коммит, на который указывает <имя ветки> . Git также поддерживает стратегию слияния «осьминог» (англ. octopus), при котором он может выполнять merge более двух веток. Для таких коммитов количество родителей будет больше двух.
Pack-файлы
«. It's worth explaining (you are probably aware of it, but
let me go through the basics anyway) how git delta-chains work, and how
they are so different from most other systems.
In other SCM's, a delta-chain is generally fixed. It might be "forwards"
or "backwards", and it might evolve a bit as you work with the repository,
but generally it's a chain of changes to a single file represented as some
kind of single SCM entity. In CVS, it's obviously the *,v file, and a lot
of other systems do rather similar things.
Git also does delta-chains, but it does them a lot more "loosely". There
is no fixed entity. Delta's are generated against any random other version
that git deems to be a good delta candidate (with various fairly
successful heursitics), and there are absolutely no hard grouping rules.
This is generally a very good thing. It's good for various conceptual
reasons (ie git internally never really even needs to care about the whole
revision chain - it doesn't really think in terms of deltas at all), but
it's also great because getting rid of the inflexible delta rules means
that git doesn't have any problems at all with merging two files together,
for example - there simply are no arbitrary *,v "revision files" that have
some hidden meaning.
It also means that the choice of deltas is a much more open-ended
question. If you limit the delta chain to just one file, you really don't
have a lot of choices on what to do about deltas, but in git, it really
can be a totally different issue».
Если кратко, то в pack-файлах объекты группируются по схожести (например, тип и размер), после чего они сохраняются в виде «цепочек». Первый элемент цепочки представляет из себя самую новую версию объекта, а следующий за ним являются диффом к предыдущему. Самые новые версии объекта считаются наиболее запрашиваемыми, поэтому они хранятся выше в цепочке.
Таким образом, Git всё же хранит диффы, но только на уровне непосредственного хранения данных. С точки зрения любого API уровнем выше, Git оперирует объектами целиком, что позволяет реализовывать различные стратегии слияния и легко разрешать конфликты.
Хранение истории
В Git нет отдельного хранилища истории. Всю историю можно развернуть, но лишь пройдя по ссылкам на родителя из нужного вам коммита. Если необходимо просмотреть историю только по одному файлу (или по поддиректории), Git всё равно должен проделать то же самое, но он будет возвращать отфильтрованные результаты. Стоит иметь это ввиду, когда вы делаете интеграцию с Git, и не заставлять Git делать полный просмотр истории на каждый файл.
К тому же, как вы могли заметить, Git не хранит информацию о переименовании файлов. Если нужно понять, переименован файл или нет, Git производит анализ содержимого хранящихся у него объектов и с некоторым (настраиваемым) допуском считает, что файл был переименован.
Merge: трехстороннее слияние (стратегия resolve)
Если нужно выполнить слияние двух веток, то git по умолчанию использует стратегию recursive, но о ней чуть позже. До того, как появилась эта стратегия, использовалась стратегия resolve, которая представляет из себя трехстороннее слияние. Для того, чтобы выполнить такое слияние, нужно иметь 3 версии: общий родитель, версия из одной ветки и версия из другой ветки. Если вы выполняете слияние файлов, то такое трехсторонее слияние может выполняться утилитой diff3, которая входит в стандартный пакет diffutils. Эта скромная и редко упоминаемая утилита, так или иначе, делает всю «грязную работу» по слиянию в большинстве существующих систем контроля версий, включая RCS, CVS, SVN и, конечно же, Git.
Помимо использования аналога diff3 (конкретная реализация, используемая в Git — это LibXDiff), Git также «на лету» вычисляет переименования файлов и использует эту информацию для слияния tree-объектов. Слияние иерархий директорий не представляет из себя ничего принципиально сложного по сравнению с тем, чтобы выполнить слияние файлов, но порождает очень много различных видов конфликтов.
Небольшая иллюстрация того, как Git выполняет трехстороннее слияние в простом случае (взято из man git-merge):
Предположим, у нас есть такая история и текущая ветка — master:
Тем не менее разработка в ветках topic и master может быть продолжена, и тогда слияние уже не будет выглядеть так просто: у нас может быть больше, чем один коммит, который подходит под определение «общий предок»:
Если мы будем использовать стратегию resolve, то будет выбран самый старый общий предок (коммит E). Если в результате выполнения merge были конфликты, разрешённые в коммите H, нам всё равно нужно будет разрешать их ещё раз.
Для выполнения слияния с помощью стратегии resolve Git возьмет коммит E в качестве общего предка и коммиты M и P в качестве двух новых версий. Если в коммите C был конфликт, то конфликтующие изменения можно откатить с помощью git revert (например, это проделано в коммите K), тогда конечное состояние M уже не будет содержать в себе конфликта, и при слиянии конфликтов тоже не будет.
Merge made by the 'recursive' strategy
Представим себе такую историю:
- cоставляем список всех общих предков, начиная с самого свежего;
- берем за текущий коммит самого первого предка;
- выполняем слияние текущего коммита со следующим предком и получаем виртуальный коммит, который берем за текущий;
- выполняем предыдущую операцию до тех пор, пока не закончится список общих предков.
Результатом выполнения этой операции будет виртуальный коммит, который представляет из себя «смерженное» состояние всех общих предков в правильном порядке — разрешение конфликтов тоже попадет в этот коммит, причем более свежие коммиты будут иметь приоритет. Когда мы получили общего предка, выполняется трехсторонее слияние, описанное выше.
Выдержка из merge-recursive.c:
Низкоуровневые команды Git
Если вы работали какое-то время с Git, то вы наверняка знаете о командах checkout, branch, pull, push, rebase, commit и некоторых других. Но изначально Git создавался не как полноценная система контроля версий, а как фреймворк для её создания. Поэтому в Git есть очень богатый набор встроенных команд, которые работают на низком уровне. Приведем некоторые из них, весьма полезные, на наш взгляд:
git rev-parse <revision>
Эта команда является очень простой: она возвращает хеш коммита для указанной ревизии. Например, git rev-parse HEAD вернет хеш коммита, на который указывает HEAD.
git rev-list <commit>.
Команда выводит список хешей коммитов по указанному запросу и может использоваться как более быстрая альтернатива git log . Например, git rev-list branch ^origin/branch ^origin/master выведет все коммиты из ветки branch, которые ещё не были запушены (при условии, что origin/branch и origin/master являются свежими, например перед этим был сделан git fetch ).
Подводные камни: Что касается запросов вида branch ^other_branch, Git может неправильно вывести результаты, если у коммитов стоит неправильное время. Например, в выводе могут быть пропущены коммиты, которые «произошли в будущем» по сравнению с merge ветки.
git diff-index
Показывает разницу между рабочей копией и индексом (.git/index). В индексе Git хранит кеш lstat() от всех файлов, о которых он знает.
git cat-file <object>
Эта команда уже встречалась в статье, но её всё же стоит упомянуть ещё раз. Она позволяет получить содержимое коммита и любого другого объекта Git.
git ls-tree <object>
Выводит содержимое tree-объекта в приемлемом виде.
git ls-remote <repository>
Выводит информацию о ветках и тегах (вместе с хешами коммитов) из указанного удаленного репозитория.
GIT_SSH
Если вы писали скрипты, которые делают git pull, то скорее всего сталкивались с тем, что SSH запрашивает подтверждение «аутентичности» удаленного репозитория, причём делает это интерактивно. Решение этой проблемы не столь изящное, потому что GIT_SSH должен быть путем к исполняемому файлу (а не опции SSH):
Заключение
Как можно было увидеть, Git позволяет действительно хорошо и надежно работать с ветками, в том числе корректно обрабатывать ситуации, когда у двух веток есть более одного общего предка. Если только вашей целью не является написание своей системы контроля версий, мы бы рекомендовали использовать результаты работы Git, а не пытаться воспроизвести его алгоритм слияния.
Надеемся, данный материал оказался интересным для вас и позволил понять, почему Git работает именно так, а не иначе. Полагаем, что статья будет также полезной для разработчиков различных интерфейсов к Git, приводя к более глубокому пониманию того, что же происходит «под капотом».
Я только что выполнил следующие команды на моем Ruby на Rails:
где Git на самом деле магазин этот репозиторий? (Это на моем локальном компьютере, но где?)
он создаст ваш репозиторий в .git папка в текущем каталоге.
чтобы быть немного более полным, Git работает с:
- the рабочее дерево (корень которого находится там, где вы сделали git init )
- "путь к репозиторию Git" (где .git , в котором будут храниться ревизии всех ваших файлов)
GIT_DIR - это переменная среды, которая может быть абсолютным или относительным путем к текущему рабочему каталогу.
если не определено, "путь к репозиторию git" по умолчанию находится в корневом каталоге вашего рабочего дерева (опять же, где вы сделали git init ).
вы можете фактически выполнить любую команду Git из любого места с вашего диска, Если вы укажете путь рабочего дерева и путь репозитория Git:
но если вы выполняете их в одном из подкаталогов репозитория Git (без указанного пути GIT-DIR или рабочего дерева), Git просто посмотрит в текущий и родительский каталоги, пока не нашел .git , предположим, что это также корневой каталог вашего рабочего дерева и используйте это .git как единственный контейнер для всех ревизий ваших файлов.
Примечание: .git также скрыт в Windows (msysgit).
Вам придется сделать dir /AH чтобы увидеть его.
git 2.9 (июнь 2016) позволяет настроить это.
обратите внимание, что Git 2.18 (Q2 2018) начинает процесс эволюции, как Git сохраняет объекты путем рефакторинга внутренней глобальной структуры данных, чтобы сделать это возможным чтобы открыть несколько репозиториев, поработайте с ними, а затем закройте их.
repository : введите поле хранилища необработанных объектов
- синтаксический анализатор необработанных объектов-это слой, который обеспечит доступ к содержимому необработанных объектов,
в то время как код анализатора объектов более высокого уровня будет анализировать необработанные объекты и отслеживает родительство и другие объектные отношения с помощью ' struct object '.
пока добавьте только нижний уровень в структуру репозитория.
если вы находитесь на английском компьютере Windows, путь хранения по умолчанию Git будет C:\Documents and Settings\< current_user>\ , потому что в Windows локальные настройки Git по умолчанию находятся в C:\Documents and Settings\< current_user>\.git и поэтому Git создает отдельную папку для каждого repo/clone at C:\Documents and Settings\< current_user>\ и есть все каталоги клонированного проекта.
например, если вы установите Symfony 2 с
каталог и файл Symfony будут в
в корневом каталоге проекта есть скрытый .git каталог, содержащий конфигурацию, репозиторий и т. д.
Я на Windows и нашел свое местоположение, щелкнув правой кнопкой мыши программу Git Bash в меню "Пуск" и выбрав "Свойства". На вкладке Ярлык отображается значение" Start in:". Для меня это было %HOMEDRIVE%%HOMEPATH% , поэтому я открыл приглашение CMD и набрал echo %HOMEDRIVE%%HOMEPATH% чтобы увидеть реальное расположение.
В a .каталог Git в корне проекта. В отличие от некоторых других систем управления версиями, в частности CVS, ни в одном из подкаталогов нет дополнительных каталогов.
Я также не смог найти свой репозиторий git. Я использую Windows 8 и создал свой репозиторий (по ошибке) под C:\Program Files (x86)\Git . Я мог видеть папку репозитория в bash, но не в cmd или Проводнике Windows.
затем я вспомнил о функции "виртуального магазина" Windows. Моя папка репозитория была фактически создана под C:\Users\<username>\AppData\Local\VirtualStore\Program Files (x86)\Git\<myrepo> и там был мой !
обычно он переходит в папку "Документы" в windows : C:\Users\\Documents\GitHub
Читайте также: