官术网_书友最值得收藏!

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/*
主站蜘蛛池模板: 永昌县| 台中县| 伊金霍洛旗| 宣汉县| 光泽县| 宜兰县| 元谋县| 阜新市| 马关县| 宜兰市| 临西县| 扶余县| 句容市| 大冶市| 阿图什市| 巴马| 财经| 正定县| 镶黄旗| 田林县| 富平县| 新兴县| 延津县| 沂源县| 华容县| 荆门市| 禹州市| 云霄县| 朝阳县| 辽宁省| 开江县| 兴安县| 连城县| 大悟县| 沙河市| 定安县| 南川市| 杭锦旗| 密云县| 阳高县| 永昌县|