occasionally when we set the default branch for a repo (from the web ui and from a put to the rest api) a git clone will not respect the default branch I saved in stash. I've verified this by performing a fresh clone, or a git branch -r from the commandline.
Here is the explanation from our Developer Bryan Turner about that feature:
Unfortunately, the feature you're using doesn't work for what you're trying to use it for. Setting the default branch in Stash has only limited control over what you will receive when you clone the repository, due to how git's wire protocol works. The real purpose of the feature is to allow customers to control which branch is selected by default in the branch selector. For example, some projects do not use "master" as their development branch, preferring to use "trunk" or "development" instead. Such repositories may not even have a "master" branch. However, git's default behaviour is for <tt>HEAD</tt> to point to <tt>refs/heads/master</tt>, which results in a pretty unpleasant user experience when browsing a repository in Stash. When hitting the "Files" or "Commits" tabs, Stash displays a warning indicating the default branch does not exist, and the user then has to go select a different branch. Setting the default branch allows Stash to display a useful initial branch, rather than a warning.
When cloning a repository, git goes through a "ref advertisement" phase where the client asks the server what refs it has available. Here's an excerpt of that from the repository hosting Stash itself:
a26508497de6d4a8fb28dcb2f4b143ef6c587317 HEAD 1c787adcaebd09e0fa923e581e09819c54b20272 refs/heads/1.0 410a8d44418450f2a4e575ab4370082f56390144 refs/heads/1.1 46da3ee9cf2854cd535d94c576cb4d7063f507e3 refs/heads/1.2 ed99a76e91d3dde8f54e1c34a086652e5f267cb6 refs/heads/1.3 710b822fee4fe3abd54cd9fd623313b3a08ad98c refs/heads/STASH-2542 6d9202cf375da3495511a98e31c6f153bb50e96c refs/heads/STASH-2673 a26508497de6d4a8fb28dcb2f4b143ef6c587317 refs/heads/master
The important thing to notice in this output is that <tt>HEAD</tt> is not sent as a name, it's sent as the commit hash it's referring to. You can see in the output that follows that <tt>refs/heads/master</tt> is pointing to the same hash. As a result, the local client assumes <tt>HEAD -> refs/heads/master</tt>. In the case of this repository, that assumption is correct.
Now, let's consider another repository I've created. The ref advertisement for that repository looks like this:
d456b884414cc5e1939a3e5ba1e7f7e5d1b6b943 HEAD d456b884414cc5e1939a3e5ba1e7f7e5d1b6b943 refs/heads/next d456b884414cc5e1939a3e5ba1e7f7e5d1b6b943 refs/heads/trunk
Notice, no "master" branch, just "next" and "trunk", and all three refs have the same hash. In the repository backing Stash, you can see that I've selected "trunk" as the default branch:
auri:51 bturner$ cat HEAD ref: refs/heads/trunk
However, cloning the repository results in this:
Cloning into 'no-master'... Password for 'http://admin@localhost:7990': remote: Counting objects: 2747, done. remote: Compressing objects: 100% (576/576), done. remote: Total 2747 (delta 886), reused 2747 (delta 886) Receiving objects: 100% (2747/2747), 1.02 MiB, done. Resolving deltas: 100% (886/886), done. auri:clones bturner$ cd no-master/ auri:no-master bturner$ git branch * next
Oops. The branch it picked was "next", not "trunk". That's because the first branch git encountered with the same hash as <tt>HEAD</tt> was "next" because it is alphabetically sorted before "trunk", and git always maintains its refs in alphabetical order (to optimize looking them up).
What this means is that if you frequently have multiple branches that point to the same hash, while setting the default branch in Stash will result in the right branch being selected by default in the branch selector, the branch checked out immediately after a clone will be the first branch, alphabetically, with a hash that matches the hash for <tt>HEAD</tt>. There are no guarantees it will be the default branch you've picked in Stash, and, unfortunately, there is no way for Stash to "fix" that; it's just how git works. If there is a specific branch you want to get immediately on cloning, you can do your clone like this:
auri:clones bturner$ git clone -b trunk http://admin@localhost:7990/stash/scm/QA/no-master.git Cloning into 'no-master'... Password for 'http://admin@localhost:7990': remote: Counting objects: 2747, done. remote: Compressing objects: 100% (576/576), done. remote: Total 2747 (delta 886), reused 2747 (delta 886) Receiving objects: 100% (2747/2747), 1.02 MiB, done. Resolving deltas: 100% (886/886), done. auri:clones bturner$ cd no-master/ auri:no-master bturner$ git branch * trunk
If you'd like to see the ref advertisement for yourself, here's how:
I hope this helps.
Connect with like-minded Atlassian users at free events near you!Find a group
Connect with like-minded Atlassian users at free events near you!
Unfortunately there are no AUG chapters near you at the moment.Start an AUG
We're bringing product updates and pro tips on teamwork to ten cities around the world.Save your spot