The refspec exemplified

Though the refspec isn't the first thing that comes to mind when thinking about the Git configuration, it is actually quite close. In a lot of the Git commands the refspec is used, but often implicitly, that is, the refspec is taken from the configuration file. If you don't remember setting a refspec configuration, you are probably right, but if you cloned the repository or added a remote, you'll have a section in .git/config, which looks something like the following (this is for the Jgit repository):

[remote "origin"]
        url = https://git.eclipse.org/r/jgit/jgit
        fetch = +refs/heads/*:refs/remotes/origin/*

The fetch line contains the configured refspec to fetch for this repository.

Getting ready

In this example, we'll be using the jgit repository as our server repository, but we have to make a clone of it to a bare repository so we can push it. You can't push to the checked out branch on a non-bare repository as this can overwrite the work area and index.

Create a bare repository from the jgit repository and create a new Git repository where we can play with the refspec as follows:

$ git clone --bare https://git.eclipse.org/r/jgit/jgit jgit-bare.git
$ git init refspec-tests
$ cd refspec-tests
$ git remote add origin ../jgit-bare.git

We also need to change the branch names on some of the branches to match the example for name spacing; the following will rename the stable-xxx branches to stable/xxx:

$ for br in $(git branch  -a | grep "stable-"); do new=$(echo $br| sed 's/-///'); git branch $new $br; done

In the previous shell scripting, the $new and $br variables aren't placed in double quotes (") as good practice for shell scripting would otherwise suggest. This is okay as the variables reflect the names of the branches in the repository and branch names cannot contain spaces.

How to do it...

Let us set up our new repository to only fetch the master branch. We do this by changing the fetch line under [remote "origin"] in the configuration file (.git/config), as follows:

[remote "origin"]
        url = ../jgit-bare.git
        fetch = +refs/heads/master:refs/remotes/origin/master

Now, we will only fetch the master branch and not all the other branches when executing a git fetch, git pull, or a git remote update origin, as follows:

$ git pull
remote: Counting objects: 44033, done.
remote: Compressing objects: 100% (6927/6927), done.
remote: Total 44033 (delta 24063), reused 44033 (delta 24063)
Receiving objects: 100% (44033/44033), 9.45 MiB | 5.70 MiB/s, done.
Resolving deltas: 100% (24063/24063), done.
From ../jgit-bare
 * [new branch]      master     -> origin/master
From ../jgit-bare
 * [new tag]         v0.10.1    -> v0.10.1
 * [new tag]         v0.11.1    -> v0.11.1
 * [new tag]         v0.11.3    -> v0.11.3
...
$ git branch –a
* master
  remotes/origin/master

Let's also set up a separate refspec to fetch all the stable/* branches to the local repository as follows:

[remote "origin"]
        url = ../jgit-bare.git
        fetch = +refs/heads/master:refs/remotes/origin/master
        fetch = +refs/heads/stable/*:refs/remotes/origin/stable/*

Now, fetch the branches locally, as shown in the following command:

$ git fetch
From ../jgit-bare
 * [new branch]      stable/0.10 -> origin/stable/0.10
 * [new branch]      stable/0.11 -> origin/stable/0.11
 * [new branch]      stable/0.12 -> origin/stable/0.12
 * [new branch]      stable/0.7 -> origin/stable/0.7
 * [new branch]      stable/0.8 -> origin/stable/0.8
 * [new branch]      stable/0.9 -> origin/stable/0.9
 * [new branch]      stable/1.0 -> origin/stable/1.0
 * [new branch]      stable/1.1 -> origin/stable/1.1
 * [new branch]      stable/1.2 -> origin/stable/1.2
 * [new branch]      stable/1.3 -> origin/stable/1.3
 * [new branch]      stable/2.0 -> origin/stable/2.0
 * [new branch]      stable/2.1 -> origin/stable/2.1
 * [new branch]      stable/2.2 -> origin/stable/2.2
 * [new branch]      stable/2.3 -> origin/stable/2.3
 * [new branch]      stable/3.0 -> origin/stable/3.0
 * [new branch]      stable/3.1 -> origin/stable/3.1
 * [new branch]      stable/3.2 -> origin/stable/3.2

We can also set up push refspecs that specify where branches are pushed to by default. Let's create a branch called develop and create one commit, as shown in the following commands:

$ git checkout -b develop
Switched to a new branch 'develop'
$ echo "This is the developer setup, read carefully" > readme-dev.txt
$ git add readme-dev.txt
$ git commit -m "adds readme file for developers"
[develop ccb2f08] adds readme file for developers
1 file changed, 1 insertion(+)
 create mode 100644 readme-dev.txt

Now, let's create a push refspec that will send the contents of the develop branch to integration/master on origin:

[remote "origin"]
    url = ../jgit-bare.git
    fetch = +refs/heads/master:refs/remotes/origin/master
    fetch = +refs/heads/stable/*:refs/remotes/origin/stable/*
    push = refs/heads/develop:refs/remotes/origin/integration/master

Let us push our commit on develop as follows:

$ git push
Counting objects: 4, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 345 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To ../jgit-bare.git
 * [new branch]      develop -> origin/integration/master

As the integration/master branch didn't exist on the remote side, it was created for us.

How it works...

The format of the refspec is in the form of <source>:<destination>. For a fetch refspec, this means that <source> is the source on the remote side and <destination> is local. For a push refspec, <source> is local and <destination> is remote. The refspec can be prefixed by a + to indicate that the ref pattern can be updated even though it isn't a fast-forward update. It is not possible to use partial globs in the refspec pattern, as shown in the following line:

fetch = +refs/heads/stable*:refs/remotes/origin/stable*

But it is possible to use namespacing. That's why we had to rewrite the stable-xxx branches to stable/xxx to fit as a namespace pattern:

fetch = +refs/heads/stable/*:refs/remotes/origin/stable/*
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset