In git
, a tag
(like many other things) is what's called a treeish. It's a way of referring to a point in the history of the project. Treeishes can be a tag, a commit, a date specifier, an ordinal specifier or many other things. A branch is just like a tag but is movable. When you are on a branch and make a commit, the branch is moved to the new commit you made indicating it's current position.
Your HEAD
is a pointer to a branch which is considered "current". Usually when you clone a repository, HEAD
will point to master which in turn will point to a commit. When you then do something like git checkout experimental
, you switch the HEAD
to point to the experimental
branch, which might point to a different commit.
When you do a git checkout v2.0
(v2.0
in this case is a tag), you are switching to a commit that is not pointed to by a branch. The HEAD
is now "detached" and not pointing to a branch. If you decide to make a commit now (as you may), there's no branch pointer to update to track this commit. Switching back to another commit will make you lose this new commit you've made.
Usually, what you can do is say git checkout -b v2.0-fixes v2.0
. This will create a new branch pointer at the commit pointed to by the treeish v2.0
(a tag in this case) and then shift your HEAD
to point to that. Now, if you make commits, it will be possible to track them (using the v2.0-fixes
branch) and you can work like you usually would.
It is also important to define the difference between the GIT_WORK_TREE
and the GIT_DIR
.
-
GIT_WORK_TREE
describes the code that is in the top level directory of your local git repo. It is what you make code changes to and commit. -
GIT_DIR
refers to the .git folder which contains the hooks folder among others.
To set up the ability to deploy from your local git repository to a remote server, you will need to start by setting up a bare git repository on that server. Create a directory and change to that directory.
mkdir ExampleApp.git
cd ExampleApp.git
git init --bare
Now if you look at what that created within the folder, you'll notice it actually created the contents of a .git
folder. This beens that this folder is now considered your GIT_DIR
. Next we need to set up this new repository as a remote within our local git repository.
git remote add production ssh://192.168.1.1/var/git/ExampleApp.git
We then just need to do our first push of our code.
git push production +master:refs/heads/master
From this point on, when ever we make a code change, we only need to run the command:
git push production
To create a tag (or release) and push that to a specific remote (or environement) you would run:
git tag -a v1.1 -m 'Version description'
git push -f production v1.1^{}:master
This last command probably looks quite scary, and it definatley requires the understanding of treeishes to comprehend. What you see in regards to v1.1^{}
is called a Tree Pointer.
Tree Pointer
This disambiguates a commit from the tree that it points to. If you want the sha that a commit points to, you can add the '{tree}' spec to the end of it.
master^{tree}
To put it simply, this crazy syntax is allowing you to place the pointer on your master branch to the sha location of your tag. From there you can run a generic git checkout -f
within your post-receive
hook and checkout that specific tag.
As for the post-receive
hook, this is a basic example that you can edit. It is based upon a Java application to show how you can compile the code, start/stop your various services, and move files around all within this hook. Notice the export statements near the beginning, they are important.
#!/bin/bash
echo "Running post-receive"
export GIT_WORK_TREE=/home/danmikita/temp
export GIT_DIR=/home/danmikita/temp/FavoriteColors.git
echo "Check out local copy"
cd $GIT_WORK_TREE
git checkout -f
echo "Maven build the new code"
mvn clean package
echo "Starting the new process under nohup"
nohup java -jar target/example-site-develop-SNAPSHOT.jar server example.yml > /var/log/example/example-log.log 2>&1 &
echo "Complete. Verify operation by visiting http://example.org/"
You can look at the man page for more on 'Tree Pointers'