How to git fetch efficiently from a shallow clone
--depth
is a git fetch
option. I see the doc doesn't really highlight that git clone
does a fetch.
When you fetch, the two repos swap info on who has what by starting from the remote's heads and searching backward for the most recent shared commit in the fetched refs' histories, then filling in all the missing objects to complete just the new commits between the most recent shared commits and the newly fetched ones.
A --depth=1
fetch just gets the branch tips and no prior history. Further fetches of those histories will fetch everything new by the above procedure, but if the previously-fetched commits aren't in the newly fetched history, fetch will retrieve all of it -- unless you limit the fetch with --depth
.
Your client did a depth=1 fetch from one repo and switched urls to a different repo. At least one long ancestry path in this new repo's refs apparently shares no commits with anything currently in your repo. That might be worth investigating, but either way unless there's some particular reason, your clients can just do every fetch --depth=1
.
Note that Git 1.9/2.0 (Q1 2014) could be more efficient in fetching for a shallow clone.
See commit 82fba2b, from Nguyễn Thái Ngọc Duy (pclouds
):
Now that git supports data transfer from or to a shallow clone, these limitations are not true anymore.
All the details are in "shallow.c
: the 8 steps to select new commits for .git/shallow
".
You can see the consequence in commits like 0d7d285, f2c681c, and c29a7b8 which support clone, send-pack /receive-pack with/from shallow clones.
smart-http now supports shallow fetch/clone too.
You can even clone form a shallow repo.
Update 2015: git 2.5+ (Q2 2015) will even allow for a single commit fetch! See "Pull a specific commit from a remote git repository".
Update 2016 (Oct.): git 2.11+ (Q4 2016) allows for fetching:
- since a date
--shallow-since=<date>
- up to a commit
--shallow-exclude=<commit>
- with a greater depth:
--deepen=N
Just did g clone github.com:torvalds/linux
and it took so much time, so I just skipped it by CTRL+C
.
Then did g clone github.com:torvalds/linux --depth 1
and it did cloned quite fast. And I have only one commit in git log
.
So clone --depth 1
should work. If you need to update existing repository, you should use git fetch origin remoteBranch:localBranch --depth 1
. It works too, it fetches only one commit.
Summing up:
Initial clone:
git clone git_url --depth 1
Code update
git fetch origin remoteBranch:localBranch --depth 1