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'm getting more and more comfortable with git, and I'm learning how to use it with my LaTeX documents. However, I'm not at all a git wizard and thus I'm looking for further advices. One can find many hints and tips around (also in TeX.SE) but I would like to focus on the issue of branching in the context of a TeX document.

I currently I find the model of one-repository-one-document optimal for my needs. By a document lets consider an article for instance. Furthermore, let's assume that the repository is also pushing to a remote location which is shared with collaborators.

My question is: When and How should I branch and merge?

I came up with an idea what should be the workflow, but I'm not sure whether it is good enough, or did I miss something. See my answer.

share|improve this question
1  
I am not sure what makes this particularly target the TeX audience, I am an avid user of git. However, from the context of your question it seems like it is a general question about distributed version control work-flow in general, could you specify what you think makes version control workflow related to TeX different from regular codes. Or is this not the intention of the question? :) –  zeroth Mar 19 '13 at 13:38
3  
I agree that it is a border case question. But, since a LaTeX document is not a regular programing project, it might have different needs, or certain conventions should be used to keep things clear. For example, within LaTeX line breaks have no importance. When it comes to VCS one probably would like to keep one line per sentence. –  Dror Mar 19 '13 at 13:50
    
Ok, your answer clarified about what you asked. For git, I would use the submodule feature which allows much more grouping, and actually makes co-peers retain the same structure for all documents. The main group can then track ALL documents while each sub-document can be tracked individually. This makes setup of reps alot easier for new users (as there is one rep, which links to all the others). Then your workflow can be applied in each of the individual documents. –  zeroth Mar 19 '13 at 13:55
    
As regards of TeX is not a regular programming project. I would probably disagree, collaboration across "real" codes is, in my case, the same. –  zeroth Mar 19 '13 at 13:56
add comment

4 Answers

I find git branching model to be useful when I am maintaining two versions of the same document, say a one column version for peer review and a two column version for the final draft. But I follow a branch and rebase strategy rather than branch and merge.

The journals that I publish in to require the authors to submit both the one column and two column versions of the manuscript. A manuscript typically requires two to three rounds of reviews before it is accepted.

Going from one column to two column usually means different line breaks in equations and sometimes different parameters to figures and tables. I usually start with the one column version of the paper. When I am ready to submit the paper, I create another branch two-column and add commits that correct the formatting of equations, figures, and tables.

When making a revision of the paper, I checkout master (one-column) branch, and make the appropriate changes. Then, to create the two-column version of the document, checkout two-column branch and then rebase it against master.

share|improve this answer
    
That's the best justification for using branches as editions I've seen so far. But I'm glad I don't have to cater for both one- and two-column editions! –  Brent.Longborough Mar 23 '13 at 10:00
add comment

An explanation of how I would do collaboration with git as a backend comes here.

The main idea is that people will have lots of documents, furthermore, it should be easy to copy the entire tree. Lastly, having the same tree for all the documents can do everybody good if TeX documents needs to use the same bib, or whatever.

A few key-points here is:

  1. Each document has its own repository (which could be remote placement in bare repos)
  2. Each document knows in principle nothing about it being a submodule.
  3. The main repos is a container, you can add any general thing here, like templates for new documents, template logos, etc.
  4. Within the main the submodules are placed. Each of these is a self contained repository with its own, independent, history, etc.
  5. The main repos does not track anything in the submodules, rather it tracks a commit-id of the submodule. Hence, this abstracts the version in the main repos somewhat, but here, the main repos is more a container than a tracker. Remember that the main tracks a commit in the submodules, and does not at will update the submodule. Thus to retrieve the latest in each document you should do:
    1. Go into the submodule and do a pull/update
    2. If this update should be put forth in the main repo you have to commit this in the main.

Ok, so I hope the above gave a brief explanation of what submodules are and do. Think of the main repo as a program, and each document as a library that is used in the program. By tracking the library one can update with out problems, and easily back-track to a working version if applicable.

See this submodule link for a more general explanation.

The main point is that once you have created a main repository which contains all the documents for your group, then you can tell your employees/co-workers to fetch that one, instead of doing, fetch this, and this, and this, and .... Also, if you are ever to do collaboration with somebody whom you do not want to share everything with, simply only give him the document repos, and not the main. You will still be able to do collaboration etc.

Ok, so I created a small bash script for you guys to play with:

#!/bin/bash

# Script for creating a couple of examples of submodule
function crt_rep {
    rm -rf $1 ; mkdir $1
    pushd $1 ; git init 
    echo "Init" > test ; git add test ; git commit -a -m "Initial, created repo $1"
    popd
}

crt_rep doc1
crt_rep doc2

# Ok, so now we have two repos...
# We create a last repo which is our parent repo
crt_rep all

# Save the current path (submodules needs full paths...)
tmp_path=$(pwd)

# Go into all and add the submodules
pushd all
# Add the submodules
git submodule add $tmp_path/doc1 doc1
git submodule add $tmp_path/doc2 doc2
# Do a status
git status
# The submodules are NOT fetched!
# This will do that (I have done it explicitly)
git submodule init doc1
git submodule update doc1
git submodule init doc2
git submodule update doc2

# Add the submodules to the repos
git commit -a -m "Added doc1 and doc2 to the repo"

# Get out
popd

# An example of tracking commits, not latest. we go into one submodule and do:
pushd doc1
echo "Second commit" > second
git add second
git commit -a -m "Added second commit"
popd
# Checkout the newest document
pushd all/doc1
git pull
popd
pushd all
git status # here, you will see that "main" has uncommitted edits (the doc1 is updated to a new commit)
popd

# Remove if the collaborator already existed 
rm -rf collaborator
# We clone everything (notice here that the COMMITED version in all is the one that
# is pulled)
git clone --recursive $tmp_path/all collaborator
# Or if, git -v < 1.6.5
#git clone $tmp_path/all collaborator
#git submodule update --init

Please go through it to see what it does.

As Brent put forth, I think you do way too many rebase statements. In my opinion, they are mostly useful for separating many branches (which I think is very overkill in this situation). All edits in the repo should be added directly in the main, if you want it to be temporary, simply name the file temporary (git tracks content, not names, so history search should be no problem here).

share|improve this answer
add comment

I hesitate to say this, but I think you're doing it wrong; but you're close to what is, I think, needed.

The purpose of a branch is to separate an activity, not a structural component.

Thus, I would not have a branch for the "Introduction" file, but for the process "Develop the Introduction". This branch might include, for example, changes not only to Introduction.tex but also to Preamble.tex (\usepackage{todonotes}, maybe) and to Master.tex (\input{Introduction}, maybe).

That said, I suspect this is only useful if you're working as part of a team -- one doing the intro, one doing chapters 1-3, one doing chapters 4-8, for example.

As a solitary author, the way I work is this (I use git):

  • To a first approximation, one repo per document
  • A master branch which represents the life of the "public" document (also known as a "release" branch)
  • If you really need it, a development branch where you accumulate other branches before release
  • Ad-hoc branches for specific major items of work (eg "I'm moving from Komascript to Memoir")
  • But normal day-to-day evolution (eg just plodding along adding paragraphs) I do on the master branch or, if I need one, the development branch.
  • Frequent commits of bite-sized changes (eg It may be useful to separate the commits for the preamble separately
  • Try to obey the maxim "Don't commit a broken version" (I try but I don't always succeed)
  • Use tagging extensively to keep notes on what a given point in the graph means

Where I am building documents that go out to clients, I also do something strange:

  • Commit everything when the document is ready (but not the direct PDF)
  • After the commit, format the document anew and check it (this brings in my git commit reference for my dogfooded gitinfo)
  • Rename the PDF output to, say, client.2013-03-19.pdf, and move it to a folder called "archive", also somewhere in the repo
  • Stage and commit the date-specific PDF, and tag that commit appropriately.

This answer, I hope, may also be helpful: Automatic branching for versions and git

share|improve this answer
    
Good points! I still think that branching can be of help even for a single author. I accept and agree with the point regarding the understanding of what should go into a branch. –  Dror Mar 19 '13 at 15:22
1  
@Dror : The main problem with your workflow as I understood it was that in swapping between branches you could lose little bits of necessary updates to things like the preamble. And I think that rebasing, while "useful when you really need it", is not something you should do very often, as it can rewrite history in subtle ways that then don't interoperate correctly with remote repos, if you need them. –  Brent.Longborough Mar 19 '13 at 15:27
    
Well, this is exactly why I posted this question. I'm not a git wizard, and I'm wondering whether and what am I doing wrong. Regarding rebase as far as I understood, it poses no problem as long as it is not involving others (remotes/collaborators) - thus I stressed that I use it on branches that are local. I'm not pushing those branches to remote. –  Dror Mar 19 '13 at 19:49
    
I have to admit that rebase is my git pons asinorum. On one occasion I comprehensively trashed a repo with it, and often get it "upside-down". Hence, probably, my reservations. –  Brent.Longborough Mar 19 '13 at 21:54
    
Good workflow, have almost an identical one. One exception the pdf I copy and rename in a dropbox folder. –  Yiannis Lazarides Mar 23 '13 at 6:43
show 1 more comment

I'll try to outline the workflow that I came up with.

In order to keep things clean, in general, there should be one branch for each of the following elements of the document:

  1. Section: Each section (or any other fundamental building block of the document) should have its own branch. These branches should be kept local, and I'd say should use the following naming convention WIP-section-name.
  2. Global Elements: By global elements I mean for example the preamble, or the reference list. Here again, the branches should be kept local and named WIP-global-settings for example.

In master the document should be, as recommended often, kept in its most polished form. Furthermore, master is the one to be shared with collaborators.

If you start a new document, then outline its structure and put placeholders for each element. Then, edit each element in its own branch. At this point, you can switch between the branches and work on each element separately. Once an element is ready it should be merged into master:

git checkout master
git merge -no-ff WIP-element-name

Nothe that I use the -no-ff switch to make sure that the history of the changes in the branch is kept.

When switching to a different branch first rebase it to the latest status of master so changes in other branches which were already integrated into master will be reflected in the branch. That is:

git checkout WIP-element-name2
git rebase master

The last piece that I could think of, is what to do with changes that you come up with while working on a certain branch, but have global influence. For example, while working on section-foo you changed the label of an image which is referenced in a different section section-bar. In this case, you should switch to the branch WIP-global-changes and implement the change (label for instance) in this branch. Then merge WIP-global-changes into master and switch back to WIP-section-foo. Don't forget to rebase WIP-section-foo to master, inorder to see the change in the label. Later, when switching to WIP-section-bar you should rebase again.

Note that I use rebase often, and therefore, in order to stay on the safe side, the branches WIP-branch-name are kept local!

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.