It appears that a lot of folks have gone to replacing git clone
with the combo git init && git fetch
. This seems rather silly, and unfortunately tools like Jenkins won't do that for you. So why does git clone not take a refspec, the same way git fetch does?
Specifically, if you wish to run a gerrit triggered build task on Jenkins, you need to ensure that the workspace exists, otherwise jenkins will fail to checkout the revision containing the gerrit change. This is because gerrit uses a ref path that is not among those fetched by a git clone.
A refspec maps a branch in the local repository to a branch in a remote repository. This makes it possible to manage remote branches using local Git commands and to configure some advanced git push and git fetch behavior.
When you clone a repository, all the tags associated with the repository will be pulled down. To fetch all the remote tags, use the fetch command as shown below. You can list down all the tags from the git repository using the following command.
git clone
can take a refspec
via the generic --config
option:
Set a configuration variable in the newly-created repository; this takes effect immediately after the repository is initialized, but before the remote history is fetched or any files checked out. [...] This makes it safe, for example, to add additional fetch refspecs to the origin remote.
Example:
git clone -c remote.origin.fetch=+refs/changes/*:refs/remotes/origin/changes/* https://gerrit.googlesource.com/git-repo
However, I just realized this does not work as expected for me with git version 2.12.2.windows.2
as the changes
ref is not really fetched when cloning. It gets properly added to .git/config
, but I need to manually fetch it after the clone via
cd git-repo
git fetch
Edit: This turns out to be known bug.
Please specify what is the refname that gerrit uses, that’s missing after the clone. And would simply git clone --origin <gerrit-suitable-origin-name>
solve the problem?
Now for the long version. Your question is probably two questions combined. Why is it advantageous to git init
, git remote add
and git fetch
, and why isn’t there a way to conveniently filter for refspecs when you initially clone the repository?
refspecs - After clone initialises a repo, the remote-refspec behaviour for the command is to add a default section to the .gitconfig that outlines the fetch spec:
[remote "origin"]
url = ssh://host/your.git
fetch = +refs/heads/*:refs/remotes/origin/*
These are good and sane defaults, and the supplied refspecs are intended to fetch everything from the remote. If you need to change the refspecs you can do it manually by just editing the file. For example,
[remote "origin"]
url = ssh://host/your.git
fetch = +refs/heads/atari:refs/remotes/origin/atari
fetch = +refs/heads/vertigo:refs/remotes/origin/vertigo
After the edit, fetching will involve only the atari
and vertigo
branches from the origin remote, and the commonly present master
for example, along with all other branches that might exist on the remote are ignored. This is of course similar to the option of supplying the refspecs to git fetch
on the command line.
Overall it just isn’t necessary, and I reckon isn’t a clean design, to be able to support multiple initial refspecs upfront on the git clone
command line, for the sole purpose of placing them in .gitconfig. You can even script much the same by running git clone
and then sed
on the .gitconfig file. It will also be problematic to decide which is the initial branch to checkout when cloning given the many possible refspecs.
init over clone - Assuming we avoid discussing the more advanced git clone
setups, such as leveraging --reference
, shallow depth with --depth
, or creating bare repos, the distinction between init-add-fetch and clone are quite minor for your everyday flow.
Plain clone just copies an existing repository and setups “origin” as the remote for the source of creation. This comes with some minor annoyances - the “origin” remote is forced on you, remote tracking branches are created, an initial branch is setup, and HEAD is checked out. If however you start with git init
you are slightly more in control. You can start manually adding remotes and fetch specific branches without checking anything out.
Note though that many aspects of git clone
behaviour can be controlled by command line switches – so maybe the developers who prefer git init
just aren’t aware of them? There isn’t enough information in the question to decide. Compared to the alternatives, git clone
saves you some typing, staves off the thermal death of the universe and sets up sane upstream defaults - such as having master a tracking branch. I vote for clone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With