List history on branch

= How Do I List All History Along a Particular Branch? =

This is probably a much more common operation than listing all history. A very common special case of this is listing all history of the current branch.

CVS
With CVS, it's fairly easy to list all revisions along a particular known branch:

cvs log -N -S -r

Note that having a space between -r and  really confuses CVS, so don't do that.

However, if the "known branch" in which you are interested is the trunk, that doesn't work, because CVS does not seem to have a way to specify the trunk as a branch. In many contexts, though, HEAD stands for the latest revision on the trunk. Thus:

cvs log -N -S -r::HEAD

lists all revisions on the trunk. (Note that in some other contexts, HEAD stands for the latest revision on the current branch.)

If you are interested in the history of the current branch, that's actually a lot harder. CVS really doesn't make it easy for you to figure out the "current" branch, possibly because each file in a working directory can have a different current branch. (Or some files can be pegged to a branch while others are pegged to a tag.)

This appears to be impossible with vanilla CVS. One possible solution is to assume that the default branch for the top-level directory is the same as everything (files or directories) under it. To find out the default branch:

cat CVS/Tag

Then:
 * if that file does not exist, you're on the trunk: use cvs log -r::HEAD.
 * if it exists and its first character is "T", you're on a branch: use cvs log -r .
 * otherwise, you're pegged to a tag and it's impossible to determine the current branch: give up.

A more complete but much more difficult solution is to determine the current branch for every file in the working tree, and then run cvs log on that file alone. E.g.:

foreach working file: run "cvs status -v " parse the "Sticky Tag" value out if "(none)": # is on the trunk run "cvs log -N -S -r::HEAD " else: look for that tag in the list of all tags if it's a branch tag: run "cvs log -N -S -r " else: error "unable to determine current branch for "

This would of course run ridiculously slowly, since it requires spawning two cvs</tt> commands for each file.

git
As mentioned above, getting the history of the current branch is easy:

git log

However, that's not quite what I was looking for, since it includes commits along this branch's parent(s), and along their parent(s), back to the beginning of time. I want to know what changes have happened on this branch, i.e. the history of this branch since its creation. If you had the foresight to tag the start of your branch, say with  -start</tt>, you're in luck:

git log -start..

If you don't have a  -start</tt> tag, I'm stumped. Clearly it's possible to figure out which branches a commit affects, as both qgit</tt> and gitk</tt> do it. But I can't figure it out.

Getting the complete history of a specific branch takes a bit more typing:

git log --

And again, the list of commits along that branch is easy if you tagged the branch start:

git log -start.. --

(Appending --</tt> is necessary in case your branch name is also a filename. git-log</tt> has a rather loose syntax for distinguishing revision names/IDs from paths, so if there's a conflict you have to sort it out with an explicit --</tt>: revision names/IDs before, paths after.)

Mercurial
When using named branches in Mercurial, one can see the history of a particular branch with this command: hg log -b The branch currently used in the working copy is shown with a: hg branch

Subversion
As with git</tt>, getting the complete history of the current branch, including revisions that affect that branch before its creation, is very easy:

svn log

Limiting the list of revisions to those made along the branch since its creation is also easy:

svn log --stop-on-copy

(Remember that a branch is just a copy, so this tells Subversion to stop when it sees the revision that copied some other sub-tree to create the current branch.)

Getting the history of a different branch is rather like getting the history across all branches: you have to step outside your working directory and pass a URL:

svn log --stop-on-copy <repo-url>/branches/

That's assuming that your repository has the conventional top-level branches</tt> directory, of course.