Git никогда толкает файлы. Git только толкает коммитов .
Каждый коммит содержит каждый файл или, точнее, каждый файл, который идет с этим коммитом, как снимок.
Например, предположим, у вас есть небольшой репозиторий с тремя коммитами:
$ git init
Initialized empty Git repository in ...
$ echo example > README.md
$ git add README.md
$ git commit -m initial
[master (root-commit) 1ba91cb] initial
1 file changed, 1 insertion(+)
create mode 100644 README.md
$ echo contents for file1 > file1.txt; git add file1.txt
$ echo contents for file2 > file2.txt; git add file2.txt
$ git commit -m commit-2
[master a232778] commit-2
2 files changed, 2 insertions(+)
create mode 100644 file1.txt
create mode 100644 file2.txt
$ echo different content > file1.txt; git add file1.txt
$ git commit -m commit-3
[master b6b2eee] commit-3
1 file changed, 1 insertion(+), 1 deletion(-)
Давайте посмотрим имена и информацию о файлах внутри commit-3:
$ git ls-tree -r HEAD
100644 blob 33a9488b167e4391ad6297a1e43e56f7ec8a294e README.md
100644 blob 802d4bbd2e8eae48bbaab3b2bb65d5b7396a374a file1.txt
100644 blob 43a59a7b12bfe183338873ba47312d0840488539 file2.txt
Мы только изменили один файл в этом третьем коммите, но все три файла находятся в нем. Как насчет имен и информации о файлах в начальном коммите?
$ git ls-tree -r HEAD~2
100644 blob 33a9488b167e4391ad6297a1e43e56f7ec8a294e README.md
Итак, это совершенно нормально: каждый коммит имеет все файлы этого коммита. Это всегда то, что вы хотите!
Где-то я читал, что github выдвигает только те файлы, которые вы добавили в последнее время ...
Здесь скрывается совершенно иная концепция , В то время как git push
толкает коммитов , каждый коммит состоит из нескольких объектов . Давайте подробнее рассмотрим третий коммит:
$ git cat-file -p HEAD | sed 's/@/ /'
tree 9a5b053002b6113f670344f397042dcf1b04ea68
parent a2327788f785cda09275bcbb02bf57121dc537ca
author Chris Torek <chris.torek gmail.com> 1586474456 -0700
committer Chris Torek <chris.torek gmail.com> 1586474456 -0700
commit-3
Обратите внимание, что сам коммит объект сам состоит из строк tree
, parent
, author
, committer
, пустая строка и текст сообщения о фиксации.
Объект tree - это то, что мы видим в выводе git ls-tree
:
$ git cat-file -p HEAD^{tree}
100644 blob 33a9488b167e4391ad6297a1e43e56f7ec8a294e README.md
100644 blob 802d4bbd2e8eae48bbaab3b2bb65d5b7396a374a file1.txt
100644 blob 43a59a7b12bfe183338873ba47312d0840488539 file2.txt
Этот объект дерева относится до трех объектов BLOB-объектов . Копия README.md
в этом древовидном объекте в точности совпадает с копией в дереве первого коммита:
$ git cat-file -p 33a9488b167e4391ad6297a1e43e56f7ec8a294e
example
Когда вы вызываете git push
, Git на самом деле упаковывает объекты для отправки коммитов. Этот пакет обычно принимает форму того, что Git называет тонкой упаковкой . Тонкий пакет использует информацию о том, какие коммиты они уже имеют , и, следовательно, какие объекты дерева и блобов они должны иметь.
Предположим, что у них уже есть первые два коммита. Ваш Git вызовет их Git и предложит коммит # 3. Они скажут: Хорошо, мне нужен этот коммит. Ваш Git также немедленно предложит коммит # 2, как это требуется здесь, но для этого они скажут: Нет, спасибо У меня есть это и все его предки. Итак, ваш Git теперь знает, что у них есть начальный и средний коммит, и это только последний, который им нужен.
Следовательно, когда вы запускаете git push origin master
, ваши Git не будут отправлять объекты 33a9488b167e4391ad6297a1e43e56f7ec8a294e
и 43a59a7b12bfe183338873ba47312d0840488539
. У Git в origin
уже есть они. Таким образом, ваш Git отправляет тонкий пакет, содержащий последний объект коммита, его последнее дерево - у них нет этого объекта - и объект для одного обновленного файла, который в данном случае является объектом с ha sh ID 802d4bbd2e8eae48bbaab3b2bb65d5b7396a374a
. Тонкая упаковка не содержит двух других объектов BLOB-объектов; они уже есть.
Они "откормят" тонкий пакет, как только получат его. Так что теперь в паке есть все необходимые предметы. У них есть все файлы, даже если вы отправили им только один! У них уже были два других.
Здесь вам ничего не нужно делать. Просто запустите git push
; Git заботится о том, чтобы выяснить, какие Git объекты требуются. Делайте обычные коммиты обычным способом, и Git выполнит работу Git.