Branches in git

Series: Why git?, Basics, Branches, Merging, Remotes

Last time we discussed starting a project and committing changes.

Now we look at how to create branches, which are one of the main reasons for having source control. We’ll cover creating branches, switching between them, and the simplest parts of merging from one to another.

Slides: Branches in git.

Passing several values through a pipe in bash

I have been fiddling with some git-related shell scripts, and decided to try and follow the same approach as git in their structure. This means using the Unix system where each piece of functionality is a separate script (or executable) that communicates by using command-line arguments, reading from the standard input stream, and writing output to the standard output stream.

This allows each piece of functionality to be written in any programming or scripting language. In git’s case this has allowed initial versions to be written in bash or perl and later optimised versions (sometimes written in C) to be dropped in, piece by piece. It’s an incredibily flexible way of working and can also be very efficient.

Most of my prototyping has been in bash, and I’ve found sometimes I need to write out multiple values from a script and collect them as input in another script.

Writing the output is simple:

#!/bin/bash

# outputter.bash

# Imagine A, B and C have been created by some complex process:
A="foo bar"
B="  bar"
C="baz   "

# At the end of our script we simply write them out on separate lines in a known order
echo "${A}"
echo "${B}"
echo "${C}"

But reading them in somewhere else gave me some trouble until I learned this recipe:

#!/bin/bash

# inputter.bash

# Read in the values one per line:
IFS=$'\n' read A
IFS=$'\n' read B
IFS=$'\n' read C

# Now we can use them.
echo "A='${A}'"
echo "B='${B}'"
echo "C='${C}'"

And now the values transfer succesfully, preserving whitespace:

$ ./outputter.bash | ./inputter.bash 
A='foo bar'
B='  bar'
C='baz   '

The recipe uses bash’s built-in read command to populate the variables, but sets the IFS variable (Internal Field Separator) to a newline, meaning all the whitespace in the line is treated as part of the value to be read. The $'\n' syntax is a literal newline.

How to use git (the basics)

Series: Why git?, Basics, Branches, Merging, Remotes

Git is a very powerful tool, but somewhat intimidating at first. I will be making some videos working through how to use it step by step.

First, we look at how to track your own code on your own computer, and then get a brief look at a killer feature: stash, which lets you pause what you were doing and come back to it later.

Slides: How to use git (the basics) slides.

Why use git for source control?

Series: Why git?, Basics, Branches, Merging, Remotes

Putting your code in git is fast, flexible and powerful. You can track versions on a single machine, or scale up to thousands of people working together, with sub-teams, reviews and cherry-picking of changes. Don’t fear branching any more:

Slides: Why use git for source control? slides.

Diffident – command line side-by-side diff editor

I really like Beyond Compare, which is a proprietary diff program with all those little touches that make it a joy to use*. The way I write code at work generally involves a bit of hacking in jEdit, checking the code myself, and then reviewing the code with a colleague.

*Recently, though, they’ve brought out a newer version that seems to overcomplicate things.

Both my own checking and the code review with a colleague generally involve comparing the code with the previous version in the (perforce) repository. Beyond Compare integrates nicely with the perforce tools and allows you to see a change as diffs of each file involved.

None of this is anything new to the Free Software world, of course. All the version control programs I’ve used allow you to do the equivalent of cvs diff and see what changes you’ve made. Git has a particularly good git diff mode which by default colours your diff and pipes it to less, making it easy to read and use.

What I have found myself missing recently, though, is the ability to edit the files as you diff them. The whole point of reviewing what you’ve done is to make changes as they occur to you, and with perforce + Beyond Compare it is really natural to make those changes within the diff tool.

Incidentally, I also really like the side-by-side style of Beyond Compare. By default it inserts “missing” lines so that all the similar lines are aligned, rather than trying to indicate with balloon-like lines that code has been inserted or transformed. I find those balloons very annoying and confusing (and they take up space on my screen, grr).

Having a side-by-side view also makes copying lines from one side to the other much easier. I often copy from one side to the other – especially when I realise what I have done is stupid and I want to revert a section back to how it was.

So, to curtail an already-long story, I decided there was yet another area of my life where the only solution was to run software I had written, rather than relying on the shoddy stuff put out by others, so I wrote a diff tool.

Diffident is a diff tool inspired by Beyond Compare and git. It shows you a side-by-side diff of your files in a terminal (one day it may have a GTK+ interface too) and allows you to edit them. The editing part is in development – expect a release fairly soon, or get the code from the git repository. The output is coloured, and you can see the whole of both files, using keyboard shortcuts to jump to the next and previous differences.

You might ask “Why not just use Beyond Compare?” For a number of reasons:

  1. It is not Free Software. I can’t improve it or trust it.
  2. It’s sort of Windows-y. I know there is a Linux version, but I bet it’s not very Linux-y. (Disclaimer: I’ve never tried it ;)
  3. It doesn’t work in a terminal.
  4. The inline editing support is not great. Its real strength is copying from side to side.
  5. It doesn’t feel right when used with git. I have got this set up in my Cygwin environment – it works, but it’s no fun.
  6. It isn’t written by me.

I’d really like Diffident to become the de-facto diff tool for git people (and everyone else). That proves to be a bit trickier than I’d like because of the way git interacts with diff tools, but I’ve got a decent solution for using it as the GIT_EXTERNAL_DIFF tool, and I hope to improve it in the future. (For those who are interested, the kind of thing I’m thinking about is how to get git diff --cached to allow me to edit the files in the index.)

So anyway, check out Diffident and if you like it, help me make it better.