Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do fetch remote branch after I cloned repo with git clone --depth 1

Tags:

git

I've repo with long history so I cloned using

git clone <url> --depth 1

Now I'm in the master branch.

How do I fetch remote branch called 'feature/my-feature' that was branched 3 commits earlier?

I've tried:

git checkout -b feature/my-feature  origin/feature/my-feature

and

git fetch -all

but I still only see master branch

like image 861
Liero Avatar asked Oct 18 '17 12:10

Liero


2 Answers

TL;DR

You need either:

git config --add remote.origin.fetch \
    +refs/heads/feature/my-feature:refs/remotes/origin/feature/myfeature

or:

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

followed by any of:

git fetch
git fetch --depth=<number>
git fetch --deepen=<number>
git fetch --unshallow

Explanation

When you make a shallow clone, Git adjusts two things:

  • the default set of branch(es) or tag(s) to be obtained and updated; and
  • the depth of the initial fetch.

(Running git clone is shorthand, as it were, for doing a long sequence of Git commands that include git init, git remote add, git fetch, and git checkout. There may be a few more commands used, if necessary.)

In particular, --depth 1 has the side effect of adding --single-branch. If you do not also cancel this out with an explicit --no-single-branch, Git will configure the fetch line, as if you had run:

git config remote.origin.fetch +refs/heads/<branch>:refs/remotes/origin/<branch>

This tells later git fetch commands to bring over only the given <branch>, and no others.

A normal (non-shallow, non-single-branch) git clone uses the default setting:

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

which tells each later git fetch to bring over every branch.

Then, having configured all future fetch operations to be single-branch, the shallow clone fetches with your specified --depth, which inserts special "graft" entries using a file named .git/shallow. These affect the overall usefulness of the clone (but much less so in any modern Git); for more about this, see Is it safe to shallow clone with --depth 1, create commits, and pull updates again? For here, though, note that this does not retain the --depth number. It just cuts short the initial fetch. The behavior of future fetches, especially those that use a different reference name, is hard to predict from this.

If you run git fetch --unshallow, Git will find all the shallow cut-offs and re-fetch all history from before this point. Then Git removes the special .git/shallow file entirely, and the clone behaves like a non-shallow clone. This is independent of whether the clone behaves like a --single-branch clone.

If you run git fetch with a specific --depth or --deepen, Git will make new shallow cut-offs as needed to set the depth to the number you specify, or increase any existing shallow cut-offs by the number you specify. If there are multiple branches, the relationship between their various cut-offs is complicated (it's all based on graph walking and without code inspection or testing, it's hard to say how Git will behave in some tricky cases).

like image 91
torek Avatar answered Nov 19 '22 03:11

torek


You could try forcing it by specifying the fetch depth:

git fetch --depth=999999

depth is the number of commits. Note that when you did a clone, clone actually does a fetch and the depth is the same depth specified in your fetch.

Make that number bigger if needed!

EDIT

Also you can/probably-should use deepen - same syntax, but it effectively fetches from where your last specified depth left off.. so its a bit more efficient:

git fetch --deepen=999999

It might depend on your git version though for that last one....

EDIT 2

Just saw this while I was reviewing the git docs....

git fetch --unshallow

This would be the best way (not sure which version it is implemented in and I have not tried it.... but looks like the thing to use).

like image 24
code_fodder Avatar answered Nov 19 '22 03:11

code_fodder