Showing posts with label git. Show all posts
Showing posts with label git. Show all posts

Tuesday, January 29, 2013

Create and track svn branches using git-svn

My most recent client is utilizing svn for the source control needs.  While I used to be a big svn guy, I've more recently been using git and have found the transition back to svn a little awkward.

Enter: git-svn.  I love git-svn because I can exist in a svn environment without giving up all the things I love about git.  One thing that continually escapes my memory is how to create a svn branch from the git CLI as well as how to associate a git branch with a svn branch.

This blog entry is my own cheat-sheet.

Say, I want to create a svn branch off of the trunk.  Here's what I would do:

$ git checkout master
$ git svn rebase
$ git svn branch -m "Creating a feature branch" feature_1001
$ git svn dcommit
$ git checkout -b my_feature_1001 feature_1001

Another thing that isn't so intuitive is merging your changes back to trunk when you're done.  Here's what I would do:


$ git checkout feature_1001
$ git rebase master
$ git checkout master
$ git merge feature_1001
$ git svn dcommit
$ git branch -D feature_1001

Then I have to use a svn client to actually delete the svn branch.

Also, if a svn branch is removed, you need to remove it by hand from git with

$ git branch -rd feature_1001



Friday, July 6, 2012

CGI Script to display clone urls


After some discussion, I was able to convince my client to convert from gitorious to gitolite.  One nice feature that people like about gitorious is that the web interface provides an easy way to look up urls for cloning repositories.

In my mind, that's a pretty legitimate need.  To that end, I threw together this bash script, which acts as a cgi and dropped it in the cgi-bin directory of the server that's running gitolite.  Hope you find this helpful.

#!/bin/bash

REPOSITORY_DIR="/home/git/repositories/"
URL_PREFIX="git clone git@internal-build-server:"

cat <<DONE
Content-type: text/html

<html>
<head>
<title>Repository URLs</title>
<link rel="stylesheet" type="text/css" href="/index.css" />
</head>
<body>
<div id="page_container">
<h1>
Repository URLs
</h1>
<p>
Repository URLs on this server follow a specific pattern.  The pattern is
as follows:
</p>
<center>
git@internal-build-server:<i><font color="darkblue">{category}</font></i>/<i><font color="darkblue">{project}</font></i>
</center>
<p>
These URLs are both pull and push URLs.  You do not need separate URLs
for pulling and pushing.  Access control will be handled by a
server git update hook that is provided by gitolite.
</p>
<p>
In an effort to make life a little easier in locating your URLs, this script
enumerates URLs for the repositories located on this machine below.
</p>
DONE

CATEGORIES=$(find $REPOSITORY_DIR -type d -maxdepth 1 -mindepth 1 -not \
-iname '*.git' | sed -e "s|$REPOSITORY_DIR||g")

for CATEGORY in $CATEGORIES; do
echo "<h2>Category: $CATEGORY</h2>"
CAT_REPOSITORIES=$(find $REPOSITORY_DIR$CATEGORY -type d -iname \
'*.git' | sed -e "s|$REPOSITORY_DIR||g" -e 's/.git$//g')
for REPOSITORY in $CAT_REPOSITORIES; do
echo "$URL_PREFIX$REPOSITORY<br />"
done
done

ROOT_REPOSITORIES=$(find $REPOSITORY_DIR -type d -maxdepth 1 -mindepth 1 \
-iname '*.git' | sed -e "s|$REPOSITORY_DIR||g" -e 's/.git$//g')
echo "<h2>Uncategorized Repositories</h2>"
for REPOSITORY in $ROOT_REPOSITORIES; do
echo "$URL_PREFIX$REPOSITORY<br />"
done

cat <<DONE
<br />
</div>
</body>
</html>
DONE

Monday, June 25, 2012

Bash script for pulling/fetching multiple git clones


In my current assignment, I'm acting as the main build guy for a number of projects that use git for source control.  As such, I find it very useful to keep all my git clones up to date whether I'm actively developing in them or not.  Additionally, I need to review the changes other developers are committing, so I'd like to get a summary of recent git activities.

Over time, I've put this little bash script together to help me with that.  I've included the script in this posting so I can remember later what/why I did this.  Disclaimer, I wrote this script and run this script in bash on Linux (not via git-bash in Windows).  Also, I'm using Zenity for some nice UI look/feel.

  1 #!/bin/bash
  2
  3 pushd ~/dev/repos > /dev/null
  4
  5 # The log file
  6 PULL_LOG="$(mktemp)"
  7
  8 # Get a list of all the clones in this directory.
  9 CLONES=$(find -maxdepth 2 -mindepth 2 -type d -name ".git" | sed -e 's|\./||' -e 's|/\.git||')
 10
 11 # Get a list of all the branches in clone/branch format
 12 ALL_BRANCHES=$(for clone in $CLONES; do cd $clone; for branch in $(git branch -l | sed 's/\s\|\*//g'); do echo $clone/$branch; done; cd ..; done)
 13
 14 # Count the branches
 15 BRANCH_COUNT=$(echo $ALL_BRANCHES | sed 's/ /\n/g' | wc -l)
 16
 17 # Start the log file
 18 echo "Pull log for $(date)" >> $PULL_LOG
 19 echo "--------------------------------------------------------------------------------" >> $PULL_LOG
 20
 21 # Function for pipping output to zenity progress dialog
 22 function pull_clones() {
 23     clone_counter=0
 24     for clone in $CLONES; do
 25         echo "Pulling branches for clone $clone" >> $PULL_LOG
 26         echo "--------------------------------------------------------------------------------" >> $PULL_LOG
 27         cd $clone
 28         echo "# Fetching changes for clone $clone"
 29         git fetch origin 2>> $PULL_LOG
 30         for branch in $(git branch -l | sed 's/\s\|\*//g'); do
 31             echo "# Merging branch $clone/$branch"
 32             echo "Merging branch $branch" >> $PULL_LOG
 33             git checkout $branch 2> /dev/null
 34             git merge origin/$branch >> $PULL_LOG
 35             echo | awk '{print count / total * 100}' count=$clone_counter total=$BRANCH_COUNT
 36             let clone_counter=clone_counter+1
 37         done
 38         cd ..
 39         echo >> $PULL_LOG
 40     done
 41 }
 42
 43 # Do it
 44 pull_clones | zenity --progress --title='Pulling development clones' --width=512
 45 zenity --text-info --filename=$PULL_LOG --title="Pull log" --width=500 --height=450
 46
 47 #Clean up
 48 rm $PULL_LOG
 49
 50 popd > /dev/null



Thursday, May 17, 2012

Gitolite... my new shiny penny

At my current client engagement, I'm serving as the build-guy and all around code librarian.  I'm managing 35 or so git repositories... keeping them tidy and organized.

Since the client seems to heavily utilize consultant help, they have a veritable revolving door of staff.  Before my arrival they decided to purchase and use a tool called gitorious to aid in managing the repositories and access to them.  It's pretty much like a private github.  It has all kinds of features including web-based management of users/keys, browse-able git logs, etc.  They have it running as an appliance on a virtual server here at the office.



It works pretty well and I've embraced it because it's the "officially-blessed-by-enterprise-architecture" tool.

It's not without it's drawbacks though:

  • In it's default configuration, EVERYONE/ANONYMOUS has READ access to ALL repositories.
  • Gitorious is heavily integrated with git's hooks, so if you want to add your own hooks to a repository, you're pretty much out of luck... unless you like tampering with their code - good luck with that.
  • If you don't want use their appliance and want to install it yourself, it's not all that straight forward.
  • The UI isn't really that intuitive.  For example if you want to see a list of tags for a repository, you have to drill into a branch rather than seeing them at the repository level.
  • It costs money if you want to have your own on-site copy.
All that said, I started looking around for alternatives for managing medium to large numbers of git repositories (more than 5'ish) both for my own stuff as well as for future clients.

In looking around, I found a tool called gitolite.  Gitolite seem to provide all the features that I want/need and has the benefits of being simple/easy to implement as well as being opensource/free.

Gitolite doesn't have a user interface.  You mange it with... what else... git!

Installation is easy

If you're running on Ubuntu, you're only a command away from installation:

steve@ubuntu64 ~ $ sudo apt-get install gitolite

That get's app installed and ready to configure.

Configuration is easy too

Instead of housing gitolite on my personal account (which you could easily do... I just choose not to), I created an account for it called git.

steve@ubuntu64 ~ $ sudo adduser git
Adding user `git' ...
Adding new group `git' (1002) ...
Adding new user `git' (1002) with group `git' ...
Creating home directory `/home/git' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for git
Enter the new value, or press ENTER for the default
        Full Name []: Git Repository Home
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] y
steve@ubuntu64 ~ $

After creating the account, you'll want to copy your public key to the git account's home directory for the one and only step of initial gitolite configuration.

steve@ubuntu64 ~ $ sudo cp .ssh/id_rsa.pub /home/git/steveb.pub
steve@ubuntu64 ~ $ sudo chown git.git /home/git/steveb.pub
steve@ubuntu64 ~ $

Now we're ready to do the initial configuration.  You'll need to become the git account to do it.

steve@ubuntu64 ~ $ su - git
Password:
git@ubuntu64:~$

Then you'll want to issue the command gl-setup from the bash prompt, passing in the key you just copied.

git@ubuntu64:~$ gl-setup steveb.pub

It will prompt you to edit the default .gitolite.rc file, but don't change anything, it's fine as it is for now.  You may have a need to change it in the future but I haven't so far.  Just save and quit out of your editor without changing anything.

The default settings in the rc file (/home/git/.gitolite.rc) are fine for most
people but if you wish to make any changes, you can do so now.

hit enter...
creating gitolite-admin...
Initialized empty Git repository in /home/git/repositories/gitolite-admin.git/
creating testing...
Initialized empty Git repository in /home/git/repositories/testing.git/
[master (root-commit) 09aad52] start
 2 files changed, 6 insertions(+)
 create mode 100644 conf/gitolite.conf
 create mode 100644 keydir/steveb.pub
git@ubuntu64:~$

That's it.  Gitolite is all set up and ready to use!

git@ubuntu64:~$ exit
logout
steve@ubuntu64 ~ $

Using gitolite is a piece-o-cake


Managing your git repositories with gitolite is done entirely by manipulating a git repository called gitolite-admin.  First let's use gitolite to create a new repository.  Step one:  clone the gitolite-admin repository from your system:

steve@ubuntu64 ~ $ cd dev
steve@ubuntu64 ~/dev $ git clone git@localhost:gitolite-admin.git
Cloning into 'gitolite-admin'...
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.
steve@ubuntu64 ~/dev $

You'll notice that the gitolite-admin clone has a pretty simple directory structure.

steve@ubuntu64 ~/dev $ cd gitolite-admin
steve@ubuntu64 ~/dev/gitolite-admin(master) $ ls -la
total 20
drwxr-xr-x  5 steve steve 4096 May 17 09:23 .
drwxrwxr-x 13 steve steve 4096 May 17 09:23 ..
drwxrwxr-x  2 steve steve 4096 May 17 09:23 conf
drwxrwxr-x  8 steve steve 4096 May 17 09:24 .git
drwxrwxr-x  2 steve steve 4096 May 17 09:23 keydir
steve@ubuntu64 ~/dev/gitolite-admin(master) $

It has two directories: conf and keydir.  The conf directory contains a file called gitolite.conf.  You edit the gitolite.conf file to create repositories and manage permissions to those repositories.

steve@ubuntu64 ~/dev/gitolite-admin(master) $ ls -l conf
total 4
-rw-rw-r-- 1 steve steve 92 May 17 09:23 gitolite.conf
steve@ubuntu64 ~/dev/gitolite-admin(master) $

The keydir directory is where you should place public key files of the users you want to grant access to repositories.  You'll notice that the public key you copied for your self is already there!

steve@ubuntu64 ~/dev/gitolite-admin(master) $ ls -l keydir
total 4
-rw-rw-r-- 1 steve steve 391 May 17 09:23 steveb.pub
steve@ubuntu64 ~/dev/gitolite-admin(master) $

Let's add that new repository.  To do so, simply edit the conf/gitolite.conf file with your favorite text editor.

steve@ubuntu64 ~/dev/gitolite-admin(master) $ vi conf/gitolite.conf

Add the following lines to it:

repo    gitolite-admin
        RW+     =   steveb
repo    testing
        RW+     =   @all
repo my_cool_new_repository
RW+ =   steveb

The two new lines in the file establish that you want to add a new repository named my_cool_new_repository and that you want to grant the user with the public key file steveb.pub full READ/WRITE/REFEDIT permissions.

Save the file. Commit it.  Then push it back to the repository origin.

steve@ubuntu64 ~/dev/gitolite-admin(master) $ git add .
steve@ubuntu64 ~/dev/gitolite-admin(master) $ git commit -m"Added new repository my_cool_new_repository"
[master 393ef15] Added new repository my_cool_new_repository
 1 file changed, 3 insertions(+)
steve@ubuntu64 ~/dev/gitolite-admin(master) $ git push
Counting objects: 7, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 433 bytes, done.
Total 4 (delta 0), reused 0 (delta 0)
remote: creating my_cool_new_repository...
remote: Initialized empty Git repository in /home/git/repositories/my_cool_new_repository.git/
To git@localhost:gitolite-admin.git
   09aad52..393ef15  master -> master
steve@ubuntu64 ~/dev/gitolite-admin(master) $

Gitolite sees your change to the conf/gitolite.conf file.  It then creates a new blank, bare git repository called my_cool_new_repository.git.  It also ensures that the steveb.pub file has the appropriate access to the git account (check out the git account's ~/.ssh/authorized_keys).

That's it.  Your new repository is ready to clone!

steve@ubuntu64 ~/dev/gitolite-admin(master) $ cd ..
steve@ubuntu64 ~/dev $ git clone git@localhost:my_cool_new_repository.git
Cloning into 'my_cool_new_repository'...
warning: You appear to have cloned an empty repository.
steve@ubuntu64 ~/dev $ cd my_cool_new_repository/
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $ date > file1.txt
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $ git add .
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $ git commit -m"Added file1.txt"
[master (root-commit) 90e1635] Added file1.txt
 1 file changed, 1 insertion(+)
 create mode 100644 file1.txt
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 257 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@localhost:my_cool_new_repository.git
 * [new branch]      master -> master
steve@ubuntu64 ~/dev/my_cool_new_repository(master) $

Adding/removing user access is as simple as adding/removing key files from the keydir directory, updating the conf/gitolite.conf file and pushing.

The gitolife.conf file, while very simple, is incredibly powerful.  It supports groups.  Also, it will not only allow you to control access to git repositories, but will also allow you to assign permissions to branches and tags with regular expressions.  Take a look at the documentation for much more info.