Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I use revision control (Subversion, to be exact) to keep track of the edits to my LaTeX documents. Is there a LaTeX package that interfaces with revision control? Specifically, it would be nice to see the revision number and time and date inside the document. (Obviously, I'd turn this off in the final version.) Also, it might be nice to get a PDF showing what was added and removed in a given revision.

share|improve this question
add comment

12 Answers

up vote 38 down vote accepted

Yes, there are packages called svn and svninfo, as well as a few for other version-control systems. See the UK TeX FAQ: you can have something like \SVNdate $Date$ which will use the value of the Date SVN variable in your document, or have footers containing the date and version number in the document. I don't think either of them shows diffs, though.

share|improve this answer
    
1 vote up. Yes these are very useful and I have been using them for a long time now. You can have these "tracking" information for each of your main tex document and for any subsidiary tex documents. This way you can keep control when you have made changes in one specific file. Unfortunately, there's no way to have these tracking information for your pictures in case you update them. –  yCalleecharan Sep 19 '10 at 19:49
1  
@yCalleecharan: that depends very much on what format your pictures are in –  SamB Dec 2 '10 at 20:53
add comment

For systems like CVS or Subversion, which modify source files, the TeX FAQ's bare-bones answer is my favourite:

\def\RCS$#1: #2 ${\expandafter\def\csname RCS#1\endcsname{#2}}
\RCS$Revision: 1.13 $ % or any RCS keyword
\RCS$Date: 2010/04/02 18:20:00 $
...
\date{Revision \RCSRevision, \RCSDate}

It's not very sophisticated, but you're only going to use it for draft versions, so this is a case where simple and robust beats pretty.

Systems like Mercurial or Git don't modify source files. In such cases, a good solution is to generate a file which can be \input into a source document. In the case of Mercurial, I use a Makefile rule like:

hg.id: .hg
    hg parent --template '\\def\\HgNode\{{node|short}}\n\\def\\HgDate\{{date|rfc3339date}}\n\\def\\HgAuthor\{{author|person}}\n' >$@

I \input that file into the document, and use \HgDate and \HgNode in \date commands or footnotes.

Update: the OP also mentioned changes between versions. That turns out to be a bit tricky in LaTeX, but the TeX FAQ has a discussion of the various (not completely satisfactory) possibilities.

Edit: More recent versions of Mercurial require the { characters in the template to be escaped. I modified the answer to include that.

Edit: hg parent is better than hg tip, as it gives the correct result if you're formatting an old (tagged?) version of the repository.

share|improve this answer
    
Mercurial has keyword extension with functionality similar to rcs keywords. –  Mekk Aug 5 '10 at 0:51
add comment

For the last part of your question, I like the Perl script latexdiff. This generates LaTeX documents displaying linebreak-insensitive differences, with changebars and other visual markup. (Alas, the implementation is quite hacky, relying on complex regular expressions for parsing, so it's worth ensuring one has Perl 5.8.10 or later installed for greater regular expression nesting depth.)

share|improve this answer
6  
and the extension latexdiff-vc can handle cvs, rcs, and svn as well –  Suresh Jul 26 '10 at 23:53
2  
Does latexdiff work if the doc is split into many files and \include'd? –  Leo Liu Aug 15 '10 at 11:41
    
I have not personally used it for multi-file documents, so can't comment. –  András Salamon Sep 7 '10 at 17:32
1  
@Leo: It's something of a nuisance, but texdiff is intended to handle this case. texdiff happily creates unbound macros, so you need to put some boilerplate in your code to handle them. –  Charles Stewart Oct 4 '10 at 9:00
    
@Charles nice. Thanks for the link. –  Leo Liu May 21 '11 at 8:01
show 1 more comment

For Git and Mercurial the only packaged option for writing revision information to the output document is the vc-bundle, which works without keyword substitution by writing to an \input’ed file.

For rendering a diff document a commit hook could be used that calls latexdiff-vc. Just inspecting diffs word-based instead of line based can be done with wdiff, or dwdiff. Git has a helpful diff mode with --color-words

git diff --color-words
share|improve this answer
    
this package work really well for me. I use the \GITHash macro. :D –  Mica Feb 2 '11 at 22:50
3  
The vc-bundle doesn't seem to provide scripts for Mercurial. (The 3 vc systems supported are Bazaar, git and svn). Does anybody have the scripts adjusted for working with Mercurial? –  Rabarberski Jun 19 '12 at 9:41
add comment

Keyword substitution is frowned on by revision control purists and is not facilitated in some modern systems such as Git and Darcs.

Solution recommended to me is to have a script generate the information and then write it to a file. Then add the information from file using \input.

share|improve this answer
2  
It is not because it is frowned upon. The whole thing just doesn't make sense and git in fact offers a much more powerful way than those offered by svn or rcs. Despite this I still don't use it. –  Leo Liu Aug 15 '10 at 11:46
    
How about \verbatiminput and not \input, all those special chars tend to break things if you are not careful. –  Johan Aug 16 '10 at 6:01
add comment

there is a nice package called gitinfo for the use with git. In combination with some easy Makefile gymnastics, this gives pretty nice results, all explained well in the manual of the package.

share|improve this answer
add comment

To get the revision id, date and time inside the document you need to use keyword substitution.

Once you've set up your repository to do the substitution you can then insert $Id$, $Revision$, $Date$ or other keywords which will then be replaced when the file is committed.

share|improve this answer
add comment

To do this I don't use a LaTeX package, but I play with a Makefile and some simple shell scripts. (But that also mean that this is a Unix/Linux/Cygwin hack).

Add something like this a Makefile

SVN_INFO=svn.info.tex
svninfo: 
    $(shell svn info > $(SVN_INFO) )

Then add something like this in a .tex file

\section{SVN info}
{\scriptsize \verbatiminput{svn.info.tex}}

Maybe with a check so you don't get a error if you don't want to include this svn info.

\IfFileExists{svn.info.tex}
{
    .....
}

This can be changed to include some kind of diff if you rather would like that.

Add something like this in your Makefile to include a diff between the current version and verison 40.

DIFF_INFO=diff.info.tex
DIFF_REV=40
diffinfo:
    $(shell svn diff --revision $(DIFF_REV) $(NAME).tex > $(DIFF_INFO) )

Then add something like this to your .tex.

\IfFileExists{diff.info.tex}
{
    \newpage
    \begin{landscape}
    \section{Diff}
    {\scriptsize \verbatiminput{diff.info.tex}}
    \end{landscape}
}

And this can then be enhanced with whatever shell scripts you feel like, so I don't see any problem doing more or less the same for other systems like git.

/Have fun

share|improve this answer
add comment

If your document uses multiple source files like \include and \input I recommend to use the 'svn-multi' package. For a changelog feature you need to use scripts like mentioned earlier, because a svn client is required to receive the log information from the server.

share|improve this answer
add comment

For better diff-s in git, set .gitattributes to *.tex diff=tex.

Configuration in my repo:

$ cat .gitattributes
*.tex    diff=tex
share|improve this answer
    
Nice, I didn't know there's a default filter for tex in git - of course there's also latexdiff+git –  Tobias Kienzler Mar 14 '13 at 10:28
add comment

Mercurial

This is a hack to say the least, but I can just as well show some code.

I write the current revision and information on which files have been modified into drafts in the following way.

I build the documents with Latexmk. In latexmkrc I add:

require('scripts/writeLatexHgInfo.pl');
writeLatexHgInfo('.hginfo');

writeLatexHgInfo.pl contains:

#!/usr/bin/perl
use strict;
use warnings;

my $HG = '/usr/bin/hg';

sub writeLatexHgInfo {
    my $template = '{node|short}|{date|rfc3339date}';
    (my $node, my $date) = split('\|', `$HG parent --template '$template'`);
    my $status = join(' \\\\'."\n", split('\n', `$HG status -mard`));

    open(HGINFO, '>'.$_[0]);
    print HGINFO
        join("\n",
            map {$_->[1] ? '\\def\\'.$_->[0].'{'.$_->[1].'}' : ()} (
                ['HgNode', $node],
                ['HgDate', $date],
                ['HgStatus', $status],
            )
        )."\n";
    close(HGINFO);
}

1;

This populates a file named .hginfo with the HG revision, the last commit date and a list of changed files since the last commit. A sample output would be:

\def\HgNode{2f2q4e1000e9}
\def\HgDate{2014-02-26T18:00:43+00:00}
\def\HgStatus{M tex/experiment.tex \\
M tex/introduction.tex}

Then I have a LaTeX package includes/hginfo.sty with contents:

\newcommand{\hginfo}{%
  \ifoptionfinal{}{%
    \input{.hginfo}
    {%
      \centering % Doesn't center, but skips parindent, for some reason.
      \begin{tikzpicture}[every node/.style={draw, dashed, align=left}]
        \node (draft) [green, label={[gray]below left:\ifdef{\HgStatus}{\HgStatus}{}}] {HG draft revision: \texttt{\HgNode/\HgDate}};
      \end{tikzpicture}
    }
  }
}

Finally, in the document I have

\usepackage{ifdraft}
\usepackage{tikz}
\usepackage{includes/hginfo}

in the preamble, and \hginfo where I want the information to go. The TikZ part is just for colored fancy layout. I use TikZ anyway, so personally it is not an "extra" dependency.


I think this solution will disappear shortly in favor of PythonTeX and Python bindings to Mercurial (EDIT: the CLI is actually the only official API; see below), but that was not available (at least not to my knowledge) when I hacked up the Perl version. I will keep it as long as it continues to work; it is only a few lines of copy+paste now that it is set up.


EDIT: I started looking at a PythonTeX version as well, but I soon realized it will not actually simplify things much; if at all. It adds files to be tracked for Latexmk, requires additional compilation runs, and includes some quirks for getting import paths correct, as it is currently written.

Anyway, this was the initial attempt:

scripts/hginfo.py

#!/usr/bin/env python
import locale
import subprocess


class HgCLI(dict):
    """Utility function for calling Mercurial CLI and returning output."""
    HG = '/usr/bin/hg'
    CMD_ERR = '--invocation error--'
    encoding = locale.getdefaultlocale()[1]

    @classmethod
    def hg_out(cls, hg_args, function=None):
        """Interpret hg_args as a list of switches for the Mercurial CLI and
        return the result. An optional second parameter defines a function to
        be applied on the result before returning.
        """
        command = [cls.HG] + hg_args
        try:
            hg_out = subprocess.check_output(command).decode(cls.encoding)
        except subprocess.CalledProcessError:
            return cls.CMD_ERR
        return hg_out if function is None else function(hg_out)


def get_hg_info():
    """Return HgDict with project data filled in."""
    return {hg_key: HgCLI.hg_out(*params) for hg_key, params in {
        'node': (['parents', '--template', '{node|short}'],),
        'date': (['parents', '--template', '{date|rfc3339date}'],),
        'status': (['status', '-mard'],
            lambda x: '\\\\'.join(x.strip().split('\n')))
        }.items()}


def main():
    print(get_hg_info())


if __name__ == '__main__':
    main()

The Mercurial CLI is called by design, since it is the official and stable API for Mercurial.

includes/hginfopy.sty

% Print fancy HG repository info in draft mode using TikZ and PythonTeX.
\newcommand{\hginfo}{%
    \ifoptionfinal{}{%
        \pyc[hg]{import sys; sys.path[-1] += '/scripts'; import hginfo; hg = hginfo.get_hg_info()}
        {%
            \centering % Doesn't center, but skips parindent, for some reason.
            \begin{tikzpicture}[every node/.style={draw, dashed, align=left}]
                \node (draft) [green, label={[gray]below left:{\py[hg]{hg['status']}}}] {HG draft revision: \texttt{\py[hg]{hg['node']}/\py[hg]{hg['date']}}};
            \end{tikzpicture}
        }
    }
}

The path kludge is there to be able to collect document related scripts in a certain directory. If hginfo.py is put in e.g. the root of the document folder, it is not needed, but it clutters the file structure. Would have been nice to have an option in PythonTeX to add a script directory to the path. I tried using the \pythontexcustomc macro to add path modifications globally, but they did not seem to propagate to the actual commands. I did not explore it in detail.

sys.path[-1] is the document root in the PythonTeX environment.

In the preamble of the LaTeX document, I add:

\usepackage[runall]{pythontex}
\usepackage{includes/hginfopy}

and where I want to render the info, I run

\hginfo

All in all, the Perl version bypasses several steps since Latexmk is already running in that environment. To get a clearer solution, it would probably be easier to spend time with the Perl function, or alternatively continue with the Python script, but call it from latexmkrc instead of via PythonTeX from within the TeX file.

share|improve this answer
1  
Since this is your first answer: Welcome to TeX.SX! –  Speravir Mar 1 at 0:45
    
@Speravir: Thanks! "Officially" been a member for four months at TeX.SE, but have been lurking for even longer. This really is a great resource. –  Daniel Andersson Mar 1 at 0:53
add comment

Regarding highlighting differences between documents under version control, there is also a discussion here: texdiff for multi-file documents in subversion

As I mentioned in that post, if you have multi-file projects in Subversion and want to highlight differences the only reliable solution I found is first to flatten the document and then run latexdiff on that document. I created a batch file that does everything, from flattening to creating a PDF highlighting the differences, automatically with one click. You can find a little tutorial and download the batch on my website http://www.jwe.cc/2012/02/workflow-with-subversion-and-latex/.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.