Configuration

90 hands-on recipes that will increase your productivity when using Git as a version control system

(For more resources related to this topic, see here.)

Configuration targets

In this section, we look at the different layers that can be configured. The layers are:

  • SYSTEM: This layer is system-wide and found in /etc/gitconfig

  • GLOBAL: This layer is global for the user and found in ~/.gitconfig

  • LOCAL: This layer is local to the current repository and found in .git/config

Getting ready

We will use the jgit repository for this example, as shown in the following command:

$ git clone https://git.eclipse.org/r/jgit/jgit $ cd jgit

How to do it...

In the previous example, we saw how we could use the command git config --list to list configuration entries. This list is actually made from three different levels of configuration that Git offers: system-wide configuration, SYSTEM; global configuration for the user, GLOBAL; and local repository configuration, LOCAL.

For each of these configuration layers, we can query the existing configuration. On a Windows box with a default installation of the Git extensions, the different configuration layers will look approximately like the following:

$ git config --list --system core.symlinks=false core.autocrlf=true color.diff=auto color.status=auto color.branch=auto color.interactive=true pack.packsizelimit=2g help.format=html http.sslcainfo=/bin/curl-ca-bundle.crt sendemail.smtpserver=/bin/msmtp.exe diff.astextplain.textconv=astextplain rebase.autosquash=true $ git config --list --global merge.tool=kdiff3 mergetool.kdiff3.path=C:/Program Files (x86)/KDiff3/kdiff3.exe diff.guitool=kdiff3 difftool.kdiff3.path=C:/Program Files (x86)/KDiff3/kdiff3.exe core.editor="C:/Program Files (x86)/GitExtensions/
GitExtensions.exe" fileeditor
core.autocrlf=true credential.helper=!\"C:/Program Files (x86)/GitExtensions/
GitCredentialWinStore/git-credential-winst
ore.exe\" user.name=Aske Olsson user.email=aske.olsson@switch-gears.dk $ git config --list --local core.repositoryformatversion=0 core.filemode=false core.bare=false core.logallrefupdates=true core.symlinks=false core.ignorecase=true core.hidedotfiles=dotGitOnly remote.origin.url=https://git.eclipse.org/r/jgit/jgit remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* branch.master.remote=origin branch.master.merge=refs/heads/master

We can also query a single key and limit the scope to one of the three layers, by using the following command:

$ git config --global user.email aske.olsson@switch-gears.dk

We can set the e-mail address of the user to a different one for the current repository:

$ git config --local user.email aske@switch-gears.dk

Now, listing the GLOBAL layer user.email will return aske.olsson@switch-gears.dk, listing LOCAL gives aske@switch-gears.dk, and listing user.email without specifying the layer gives the effective value that is used in the operations on this repository, in this case, the LOCAL value aske@switch-gears.dk. The effective value is the value, which takes precedence when needed. When two or more values are specified for the same key, but on different layers, the lowest layer takes precedence. When a configuration value is needed, Git will first look in the LOCAL configuration. If not found here, the GLOBAL configuration is queried. If it is not found in the GLOBAL configuration, the SYSTEM configuration is used. If none of this works, the default value in Git is used.

In the previous example, user.email is specified in both the GLOBAL and LOCAL layers. Hence, the LOCAL layer will be used.

How it works...

Querying the three layers of configuration simply returns the content of the configuration files: /etc/gitconfig for system-wide configuration, ~/.gitconfig for user-specific configuration, and .git/config for repository-specific configuration. When not specifying the configuration layer, the returned value will be the effective value.

There's more...

Instead of setting all the configuration values on the command line by the key value, it is possible to set them by just editing the configuration file directly. Open the configuration file in your favorite editor and set the configuration you need, or use the built-in git config -e repository to edit the configuration directly in the Git-configured editor. You can set the editor to the editor of your choice either by changing the $EDITOR environment variable or with the core.editor configuration target, for example:

$ git config --global core.editor vim

Querying the existing configuration

In this example, we will look at how we can query the existing configuration and set the configuration values.

Getting ready

We'll use jgit again by using the following command:

$ cd jgit

How to do it...

To view all the effective configurations for the current Git repository, run the following command:

$ git config --list user.name=Aske Olsson user.email=askeolsson@switch-gears.dk core.repositoryformatversion=0 core.filemode=false core.bare=false core.logallrefupdates=true remote.origin.url=https://git.eclipse.org/r/jgit/jgit remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* branch.master.remote=origin branch.master.merge=refs/heads/master

The previous output will of course reflect the user running the command. Instead of Aske Olsson as the name and the e-mail, the output should reflect your settings.

If we are just interested in a single configuration item, we can just query it by its section.key or section.subsection.key:

$ git config user.name Aske Olsson $ git config remote.origin.url https://git.eclipse.org/r/jgit/jgit

How it works...

Git's configuration is stored in plaintext files, and works like a key-value storage. You can set/query by key and get the value back. An example of the text-based configuration file is shown as follows (from the jgit repository):

$ cat .git/config [core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true [remote "origin"] url = https://git.eclipse.org/r/jgit/jgit fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master

There's more...

It is also easy to set configuration values. Just use the same syntax as when querying the configuration except add an argument to the value. To set a new e-mail address on the LOCAL layer, we can execute the following command line:

git config user.email askeolsson@example.com

The LOCAL layer is the default if nothing else is specified. If you require whitespaces in the value, you can enclose the string in quotation marks, as you would do when configuring your name:

git config user.name "Aske Olsson"

You can even set your own configuration, which does not have any effect on the core Git, but can be useful for scripting/builds and so on:

$ git config my.own.config "Whatever I need"

List the value

$ git config my.own.config Whatever I need

It is also very easy to delete/unset configuration entries:

$ git config --unset my.own.config

List the value

$ git config my.own.config

Templates

In this example, we will see how to create a template commit message that will be displayed in the editor when creating a commit. The template is only for the local user and not distributed with the repository in general.

Getting ready

In this example, we will use the example repository:

$ git clone https://github.com/dvaske/data-model.git $ cd data-model

We'll use the following code as a commit message template for commit messages:

Short description of commit Longer explanation of the motivation for the change Fixes-Bug: Enter bug-id or delete line Implements-Requirement: Enter requirement-id or delete line

Save the commit message template in $HOME/.gitcommitmsg.txt. The filename isn't fixed and you can choose a filename of your liking.

How to do it...

To let Git know about our new commit message template, we can set the configuration variable commit.template to point at the file we just created with that template; we'll do it globally so it is applicable to all our repositories:

$ git config --global commit.template $HOME/.gitcommitmsg.txt

Now, we can try to change a file, add it, and create a commit. This will bring up our preferred editor with the commit message template preloaded:

$ git commit Short description of commit Longer explanation of the motivation for the change Fixes-Bug: Enter bug-id or delete line Implements-Requirement: Enter requirement-id or delete line # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: another-file.txt # ~ ~ "\.git/COMMIT_EDITMSG" 13 lines, 396 characters

We can now edit the message according to our commit and save to complete the commit.

How it works...

When commit.template is set, Git simply uses the content of the template file as a starting point for all commit messages. This is quite convenient if you have a commit-message policy as it greatly increases the chances of the policy being followed. You can even have different templates tied to different repositories, since you can just set the configuration at the local level.

A .git directory template

Sometimes, having a global configuration isn't enough. You will also need to trigger the execution of scripts (aka Git hooks), exclude files, and so on. It is possible to achieve this with the template option set to git init. It can be given as a command-line option to git clone and git init, or as the $GIT_TEMPLATE_DIR environment variable, or as the configuration option init.templatedir. It defaults to /usr/share/git-core/templates. The template option works by copying files in the template directory to the .git ($GIT_DIR) folder after it has been created. The default directory contains sample hooks and some suggested exclude patterns. In the following example, we'll see how we can set up a new template directory, and add a commit message hook and exclude file.

Getting ready

First, we will create the template directory. We can use any name we want, and we'll use ~/.git_template, as shown in the following command:

$ mkdir ~/.git_template

Now, we need to populate the directory with some template files. This could be a hook or an exclude file. We will create one hook file and an exclude file. The hook file is located in .git/hooks/name-of-hook and the exclude file in .git/info/exclude. Create the two directories needed hooks and info, as shown in the following command:

$ mkdir ~/.git_template/{hooks,info}

To keep the sample hooks provided by the default template directory (the Git installation), we copy the files in the default template directory to the new one. When we use our newly created template directory, we'll override the default one. So, copying the default files to our template directory will make sure that except for our specific changes the template directory is similar to the default one, as shown in the following command:

$ cd ~/.git_template/hooks $ cp /usr/share/git-core/templates/hooks/* .

We'll use the commit-msg hook as the example hook:

#!/bin/sh MSG_FILE="$1" echo "\nHi from the template commit-msg hook" >> $MSG_FILE

The hook is very simple and will just add Hi from the template commit-msg hook to the end of the commit message. Save it as commit-msg in the ~/.git_template/hooks directory and make it executable by using the following command:

chmod +x ~/.git_template/hooks/commit-msg

Now that the commit message hook is done, let's also add an exclude file to the example. The exclude file works like the .gitignore file, but is not tracked in the repository. We'll create an exclude file that excludes all the *.txt files, as follows:

$ echo *.txt > ~/.git_template/info/exclude

Now, our template directory is ready for use.

How to do it...

Our template directory is ready and we can use it, as described earlier, as a command-line option, an environment variable or, as in this example, to be set as a configuration:

$ git config --global init.templatedir ~/.git_template

Now, all Git repositories we create using init or clone will have the default files of the template directory. We can test if it works by creating a new repository as follows:

$ git init template-example $ cd template-example

Let's try to create a .txt file and see what git status tells us. It should be ignored by the exclude file from the template directory:

$ echo "this is the readme file" > README.txt $ git status

The exclude file worked! You can put in the file endings yourself or just leave it blank and keep to the .gitignore files.

To test if the commit-msg hook also works, let us try to create a commit. First, we need a file to commit. So, let's create that and commit it as follows:

$ echo "something to commit" > somefile $ git add somefile $ git commit –m "Committed something"

We can now check the history with git log:

$ git log -1 commit 1f7d63d7e08e96dda3da63eadc17f35132d24064 Author: Aske Olsson <aske.olsson@switch-gears.dk> Date: Mon Jan 6 20:14:21 2014 +0100 Committed something Hi from the template commit-msg hook

How it works...

When Git creates a new repository, either via init or clone, it will copy the files from the template directory to the new repository when creating the directory structure. The template directory can be defined either by a command-line argument, environment variable, or configuration option. If nothing is specified, the default template directory will be used (distributed with the Git installation). By setting the configuration as a --global option, the template directory defined will apply to all of the user's (new) repositories. This is a very nice way to distribute the same hooks across repositories, but it also has some drawbacks. As the files in the template directory are only copied to the Git repositories, updates to the template directory do not affect the existing repositories. This can be solved by running git init in each existing repository to reinitialize the repository, but this can be quite cumbersome. Also, the template directory can enforce hooks on some repositories where you don't want them. This is quite easily solved by simply deleting the hook files in .git/hooks of that repository.

A few configuration examples

There are configuration targets in the core Git system. In this section, we'll take a closer look at a few of them that might be useful in your daily work.

We'll look at the following three different configuration areas:

  • Rebase and merge setup

  • Expiry of objects

  • Autocorrect

Getting ready

In this exercise, we'll just set a few configurations:

$ cd data-model

How to do it...

Let's take a closer look at the previously mentioned configuration areas.

Rebase and merge setup

By default, when performing git pull, a merge commit will be created if the history of the local branch has diverged from the remote one. However, to avoid all these merge commits, a repository can be configured so it will default to rebase instead of merging when doing git pull. Several configuration targets related to the option exist as follows:

  • pull.rebase: This configuration, when set to true, will pull to rebase the current branch on top of the fetched one when performing a git pull. It can also be set to preserve so that the local merge commit will not be flattened in the rebase, by passing --preserve-merges to git rebase. The default value is false as the configuration is not set. To set this option in your local repository, run the following command:

    $ git config pull.rebase true

  • branch.autosetuprebase: When this configuration is set to always, any new branch created with <git branch or git checkout that tracks another branch will be set up to pull to rebase (instead of merge). The valid options are as follows:

    • never: This is set to pull to rebase (default)

    • local: This is set to pull to rebase for local tracked branches

    • remote: This is set to pull to rebase for remote tracked branches

    • always: This is set to pull to rebase for all tracked branches

    To set this option for all the new branches regardless of tracking remote or local branches, run the following command:

    $ git config branch.autosetuprebase always

  • branch.<name>.rebase: This configuration, when set to true, applies only to the <name> branch and tells Git to pull to rebase when performing git pull on the given branch. It can also be set to preserve so that the local merge commit will not be flattened when running git pull. By default, the configuration is not set for any branch. To set the feature/2 branch in the repository to default to rebase instead of merge, we can run the following command:

    $ git config branch.feature/2.rebase true

Expiry of objects

By default, Git will perform garbage collection on unreferenced objects and clean reflog for entries, both of which are older than 90 days. For an object to be referenced, something must point to it; a tree, a commit, a tag, a branch, or some of the internal Git bookkeeping like stash or reflog. There are three settings that can be used to change this time as follows:

  • gc.reflogexpire: This is the general setting to know for how long a branch's history is kept in reflog. The default time is 90 days. The setting is a length of time, for example, 10 days, 6 months and it can be turned completely off with the value never. The setting can be set to match a refs pattern by supplying the pattern in the configuration setting. gc.<pattern>.reflogexpire: This pattern can, for example, be /refs/remotes/* and the expire setting would then only apply for those refs.

  • gc.reflogexpireunreachable: This setting controls how long the reflog entries that are not a part of the current branch history should be available in the repository. The default value is 30 days, and similar to the previous option, it is expressed as a length of time or set to never in order to turn it off. This setting can, as the previous one, be set to match a refs pattern.

  • gc.pruneexpire: This option tells git gc to prune objects older than the value. The default is 2.weeks.ago, and the value can be expressed as a relative date like 3.months.ago. To disable the grace period, the value now can be used. To set a non-default expiry date only on remote branches, use the following command:

    $ git config gc./refs/remote/*.reflogexpire never $ git config gc./refs/remote/*.reflogexpireunreachable "2 months"

    We can also set a date so git gc will prune objects sooner:

    $ git config gc.pruneexpire 3.days.ago

Autocorrect

This configuration is useful when you get tired of messages like the following one just because you made a typo on the keyboard:

$ git statis git: 'statis' is not a git command. See 'git --help'. Did you mean this? status

By setting the configuration to help.autocorrect, you can control how Git will behave when you accidentally send a typo to it. By default, the value is 0 and it means to list the possible options similar to the input (if statis is given status will be shown). A negative value means to immediately execute the corresponding command. A positive value means to wait the given number of deciseconds (0.1 sec) before running the command, (so there is some amount of time to cancel it). If several commands can be deduced from the text entered, nothing will happen. Setting the value to half a second gives you some time to cancel a wrong command, as follows:

$ git config help.autocorrect 5 $ git statis WARNING: You called a Git command named 'statis', which does not exist. Continuing under the assumption that you meant 'status' in 0.5 seconds automatically... # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: another-file.txt #

How it works...

Setting the configuration targets will change the way Git behaves. The previous examples describe a few useful methods to get Git to act differently than its default behavior. You should be sure when you are changing a configuration that you completely understand what that configuration does. So, check the Git configuration help page by using git help config.

There's more...

There are a lot of configuration targets available in Git. You can run git help config and a few pages down all of them are displayed and explained.

Git aliases

An alias is a nice way to configure long and/or complicated Git commands to represent short useful ones. An alias is simply a configuration entry under the alias section. It is usually configured to --global to apply it everywhere.

Getting ready

In this example, we will use the jgit repository, with the master branch pointing at b14a93971837610156e815ae2eee3baaa5b7a44b. Clone the repository again, as follows:

$ git clone https://git.eclipse.org/r/jgit/jgit $ cd jgit $ git checkout master && git reset --hard b14a939

How to do it...

First, we'll create a few simple aliases, then a couple of more special ones, and finally a couple of aliases using external commands. Instead of writing git checkout every time we need to switch branches, we can create an alias of that command and call it git co. We can do the same for git branch, git commit, and git status as follows:

$ git config --global alias.co checkout $ git config --global alias.br branch $ git config --global alias.ci commit $ git config --global alias.st status

Now, try to run git st in the jgit repository as follows:

$ git st # On branch master nothing to commit, working directory clean

The alias method is also good to create the Git commands you think are missing in Git. One of the common Git aliases is unstage, which is used to move a file out of the staging area, as shown in the following command:

$ git config --global alias.unstage 'reset HEAD --'

Try to edit the README.md file in the root of the jgit repository and add it in the root. Now, git status/git st should display something like the following:

$ git st # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: README.md #

Let's try to unstage README.md and then look at git st as follows:

$ git unstage README.md Unstaged changes after reset: M README.md $ git st # On branch master # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in
working directory)
# # modified: README.md # no changes added to commit (use "git add" and/or "git commit -a")

A common use case for aliases is to format the history of Git in specific ways. Let's say you want the number of lines added and deleted for each file in the commit displayed along with some common commit data. For this, we can create the following alias so we don't have to type everything each time:

$ git config --global alias.ll "log --pretty=format:\"%C(yellow)
%h%Cred%d %Creset%s %Cgreen(%cr) %C(bold blue)
<%an>%Creset\" --numstat"

Now, we can execute git ll in the terminal and get a nice stat output, as shown in the following command:

$ git ll b14a939 (HEAD, master) Prepare 3.3.0-SNAPSHOT builds
(8 days ago) <Matthias Sohn>
6 6 org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF 1 1 org.eclipse.jgit.ant.test/pom.xml 3 3 org.eclipse.jgit.ant/META-INF/MANIFEST.MF 1 1 org.eclipse.jgit.ant/pom.xml 4 4 org.eclipse.jgit.archive/META-INF/MANIFEST.MF 2 2 org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF 1 1 org.eclipse.jgit.archive/pom.xml 6 6 org.eclipse.jgit.console/META-INF/MANIFEST.MF 1 1 org.eclipse.jgit.console/pom.xml 12 12 org.eclipse.jgit.http.server/META-INF/MANIFEST.MF ...

It is also possible to use an external command instead of a Git command. So, small shell scripts and so on can be embedded. To create an alias with an external command, the alias must start with an exclamation mark !. The examples can be used when resolving conflicts from a rebase or merge. In your ~/.gitconfig file under [alias], add the following:

editconflicted = "!f() {git ls-files --unmerged |
cut -f2 | sort -u ; }; $EDITOR 'f'"

This will bring up your configured $EDITOR with all the files that are in the conflict state due to the merge/rebase. This quickly allows you to fix the conflicts and get on with the merge/rebase.

In the jgit repository, we can create two branches at an earlier point in time and merge these two branches:

$ git branch A 03f78fc $ git branch B 9891497 $ git checkout A Switched to branch 'A' $ git merge B

Now, you'll see that this fails to perform the merge, and you can run git st to check the status a lot of files are in a conflicted state, both modified. To open and edit all the conflicted files, we can now run git editconflicted. This brings up $EDITOR with the files. If your environment variable isn't set, use EDITOR=<you-favorite-editor> export to set it.

For this example, we don't actually resolve the conflicts. Just check that the alias works and you're ready for the next alias.

Now that we have solved all the merge conflicts, it is time to add all of those files before we conclude the merge. Luckily, we can create an alias that can help us with that, as follows:

addconflicted = "!f() { git ls-files --unmerged |
cut -f2 | sort -u ; }; git add 'f'"

Now, we can run git addconflicted. Later, git status will tell us that all the conflicted files are added:

$ git st On branch A All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: modified: org.eclipse.jgit.console/META-INF/MANIFEST.MF modified: org.eclipse.jgit.console/pom.xml modified: org.eclipse.jgit.http.server/META-INF/MANIFEST.MF modified: org.eclipse.jgit.http.server/pom.xml modified: org.eclipse.jgit.http.test/META-INF/MANIFEST.MF modified: org.eclipse.jgit.http.test/pom.xml ...

Now we can conclude the merge with git commit:

$ git commit [A 94344ae] Merge branch 'B' into A

How it works...

Git simply runs the command the alias is short for. It is very convenient for long Git commands, or Git commands that are hard, to remember exactly how to write. Now, all you have to remember is the alias and you can always look in the configuration file for it.

There's more...

Another way to create a kind of Git alias is to make a shell script and save the file with the name git-<your-alias-name>. Make the file executable and place it somewhere in your $PATH. You can now run that file simply by running git <your-alias-name> from the command line.

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 any 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/*

Summary

In this article, we learned cover configuration targets, querying the existing configuration, templates, a .git directory template, a few configuration examples, Git aliases, and the refspec exemplified.

Resources for Article:


Further resources on this subject:


Books to Consider

WildFly Configuration, Deployment, and Administration - Second Edition
$ 29.99
JBoss EAP Configuration, Deployment, and Administration [Video]
$ 25.50
IBM Rational ClearCase 7.0: Master the Tools That Monitor, Analyze, and Manage Software Configurations
$ 32.99
comments powered by Disqus
X

An Introduction to 3D Printing

Explore the future of manufacturing and design  - read our guide to 3d printing for free