If we use the git clone --branch
command, we're only copying the specified branch. What is the additional --single-branch
param used fo? The documentation isn't clear to me.
TIA
If we use the git clone --branch
command, we're only copying the specified branch. What is the additional --single-branch
param used fo? The documentation isn't clear to me.
TIA
--branch foo
automatically checks out foo
after the clone is done but the clone downloads all the branches/tags and their reachable data.
--branch foo --single-branch
tells git-clone to download only the data reachable from foo
and check out foo
.
If we use the
git clone --branch
command, we're only copying the specified branch.
No, you're cloning the entire repository and checking out that branch.
As ElpieKay answered, git clone --branch name url
is (my paraphrase) very roughly equivalent to:
(git clone url && cd clone-target-directory && git checkout name)
—i.e., it does a full clone. (The parentheses above are because your main command interpreter does not change directories, so to simulate this, we need to do the cd
in a sub-shell.)
The git clone
command itself is short-hand for a series of more-primitive Git operations. All get done in a new directory,1 which I'll show as step 1 here, but note that your command interpreter itself stays outside this new directory so you end up having to do your own separate cd
into the new directory. Some options are incompatible or set other options, e.g., using --depth
sets --single-branch
by default.2 These are built in to a single command, rather than actually having git clone
invoke each separate Git command, but assuming the whole clone succeeds, the effect is the same as if you manually run each of these commands.3
mkdir target && cd target
. The target directory is the one you specify, or the one computed from the URL you give to git clone
. See footnote 1 again.
git init
, to create the new, empty repository.
If you use the --bare
or --mirror
flags, git clone
will configure the repository as a bare clone or mirror clone here, as if by running git init --bare
instead.
git remote add origin url
, so that the name origin
identifies the url
argument you give to git clone
.
You can get git clone
to do additional configuration here as well; see the -c
/ --config
option.
If you use the -o
or --origin
flag, you can change the name from origin
to any other name you like. The rest of this assumes that you did not.
If you use the --single-branch
flag, git config remote.origin.fetch +refs/heads/branch:refs/remotes/origin/branch
. This overrides the default that git remote add
creates. The default setting tells Git: bring over every branch. This particular setting tells Git: bring over only the one named branch. See footnote 2 here as well.
In either case, after bringing over each branch tip commit (and all commits reachable from these tips), your Git renames the branches it got from the other Git, so that instead of actual branch names, these become remote-tracking names: refs/remotes/origin/whatever
.
If you use the --mirror
option during git clone
, Git will override all of these and set the fetch refspec to +refs/*:refs/*
. (It's not clear how --mirror
should interact with --single-branch
.)
git fetch origin
: this step actually contacts the other Git—the one at url
—and obtains from it the list of references (branch and tag names, and so forth) to get the list of tip commits to bring over. The commits brought over depend on the remote.origin.fetch
setting set up in step 4, if any, or the default set up in step 3.
Last, as long as this is not a bare clone (neither --bare
nor --mirror
), git checkout branch
. The argument to the git checkout
step is chosen from the best match in this list:4
-b
/ --branch
master
This git checkout
command actually creates your local branch, using the same commit that the copied remote-tracking name identifies. For instance, if you said to check out -b xyz
, your git fetch
will have brought over their refs/heads/xyz
and renamed it to your refs/remotes/origin/xyz
. This git checkout
then creates your own refs/heads/xyz
, pointing to the same commit as your refs/remotes/origin/xyz
, which of course points to the commit that their Git has (or had) as their refs/heads/xyz
.
(If you name a tag with your -b
option, your Git creates no branches in your own repository.)
Hence, while both -b
and --single-branch
allow you to pick your own branch name, they have different effects earlier in the sequence of steps that git clone
runs.
1The exception to this rule occurs when you run git clone url directory
to tell git clone
to put the clone into the given but existing directory, e.g., .
. For Git to allow this, the given directory must be empty.
2If you use git clone --single-branch
(even if it's just implied), Git will clone the particular branch you specify with -b
/ --branch
. If you don't choose one with this option, Git will choose one for you, using the method shown in step 6.
3If the git clone
operation fails, Git will clean up after itself, removing the entire new directory, or everything created in the empty directory.
4In order to choose the right branch, your Git has to ask the other Git what its HEAD
is. In Git versions before 1.8.5, there is no way to find out. If either Git involved in the cloning process predates 1.8.5, your Git will have the other Git list all its branch names and their hash IDs, and then list the hash ID that goes with their HEAD
, and guess which branch that might be. If both Gits are at least 1.8.5, your Git will just get their Git to send you their recommended branch name—there's no need to guess when both Gits support the "read symbolic HEAD" capability.