2013-09-29
Git is a source control management system that you can use to track changes in any text file. Git, however, is quite complicated and learning it can be quite time consuming. This is a quick introduction to git for someone who will primarily use git to edit LaTeX/text documents (not code) and possibly collaborate with a handful of co-authors.
Here are a few benefits you get when using git
.
You can display word by word changes made in a form that looks like this:
@@ -3045,12 +3045,15 @@ \section{Proof of Proposition~\ref{ppnCLTFirstHitShort}} We finally define the function $g$ that appearsappearing in Property (6). Forfor $x = (q,\xi) \in \CM$, letby setting $g((q,\xi)) = \xi \in \mathbb{Z}^2$.
Or inspect changes line by line:
diff --git a/refs.bib b/refs.bib index 349c0c3..65b8321 100644 --- a/refs.bib +++ b/refs.bib @@ -5556,7 +5585,7 @@ pages = {2636--2647} } -@Book{ Rozovski90, +@Book{ Rozovskii90, author = {Rozovski{\u\i}, B. L.}, title = {Stochastic evolution systems}, series = {Mathematics and its Applications (Soviet Series)},
Or as a compiled PDF using latexdiff (setup instructions are here):
If you and a co-author are working on a file at the same time, git will NEVER allow you to accidentally overwrite each others changes because you “edited the wrong version”.
In this case when you push your changes, git
will inform you of a conflict.
Often, if you and your co-authors edited different files, or even different parts of the same file, git
can automatically merge your changes for you.
If you and your co-author edited the same part of a file, git
will inform you, and leave conflict markers in the file showing the differences.
These look something like this:
In 1875, Galton and Watson~\cite{WatsonGalton75} took up an investigation into the phenomenon of ``the decay of the families of men who occupied conspicuous positions in past times.'' <<<<<<< HEAD:paper.tex The problem, posed by Galton, was summarized by the Rev. H. W. Watson as follows. ======= The problem was summarized by the Rev. H. W. Watson as follows. >>>>>>> fe933fa:paper.tex
Now you can edit the file, and tell git
when you have “resolved all conflicts”.
With git
you have full access to older versions at all times.
(This, in some sense, is the point of version control).
Some of the things you can do are:
Restore old versions, or temporarily view them, or compare them.
Search for when a phrase was first introduced.
Find out who/when a particular line was changed.
You don’t have to abandon your favorite cloud storage (like Dropbox, Box, Google Drive, etc.) to use git
.
If you use cloud storage to synchronize files on your computer, you can simply run git
inside your “cloud folder”.
(Look here for instructions on making git
and dropbox
work well together.)
Main caveat: If you run git
inside your cloud folder, be sure you only use that folder to synchronize between your own personal computers – don’t ever share this folder with a co-author otherwise there will be trouble.
The first thing you should do is install git. If you’re not a command line geek, then you might consider installing a GUI. I’ve heard good things about SourceTree, but there are many other choices.
Introduce yourself to git. If your GUI client doesn’t let you do this directly, open a terminal and type:
git config --global user.name 'Your Name' git config --global user.email you@math.youruniv.edu
In order to share changes with others you will (almost surely) need an SSH key.
If you don’t have one already, instructions on how do this can be found here.
If you are using my git server to share changes, you will need to email me your SSH public key.
This is usually a file called id_rsa.pub
in your SSH directory (~/.ssh
in Linux).
Don’t ever share your private key (usually a file called id_rsa
without the .pub
extension).
Every paper is stored in a git repository.
The first thing you have to do is to get the repository URL and then clone it.
For papers on my git server the repository URL will look something like git@wiki.math.cmu.edu:papers/201401-xxx
.
Now you can clone the repository by typing following into a terminal.
git clone git@wiki.math.cmu.edu:papers/201401-xxx myfolder
or using your GUI client. (myfolder
above is the name of a directory you want to use for this project.)
To fetch changes that others might have made when you are away you have to pull them. Most GUI clients can do this directly. On a terminal, change to your project directory first and type
git pull
If you have any local changes, don’t worry.
A git pull
will never overwrite your changes.
If your locally modified files have also been modified by others, then git will abort with an error message and you need to merge the changes (described below) to proceed.
You can edit the files in the project as you please. When you are done making changes and are ready to share them, you have to commit them and then push them. Committing tells git to save your current changes into your local git repository (not the server). Anything committed into git can be easily resurrected at any time, or compared to the current files or anything else committed into git. Once you have committed your changes, you should push them. This sends your changes to the server for other co-authors to pull.
Most GUI’s will handle committing. If you prefer the terminal, use
git commit -a
to commit all locally modified files that are currently tracked by git. This will open an editor into which you can type a commit message. TYPE A USEFUL COMMIT MESSAGE. The first line of your commit message should be short, and is called the commit subject. You can optionally provide a more detailed explanation. To do this, leave one blank line after your commit subject and then type a longer message explaining your changes. When you are done, save your changes and close your editor to finish the commit.
Committing is actually a multi-step process: You’re supposed to first stage files by using
git add file.tex ...
and then commit them using git commit
.
The git commit -a
above stages all locally modified files, and commits them.
You can do this most of the time.
The most common exception is when you create a new file.
In this case you have to first add it using git add ...
and then commit it.
To see what files have been modified, staged, etc. use git status
.
(More detailed information is in the documentation here)
Committing your changes DOES NOT automatically push them. For others to see your changes, you have to push your changes. Most GUIs will handle pushing. On a terminal you can do this by typing
git push
This should work “most of the time”. Sometimes, git will abort with a message saying “Non-fast forward updates were rejected”. This happens when someone else made a change which you did not pull before making your changes. In this case, you have to pull their changes, merge them, and then push your changes.
In the normal workflow of a math paper with a handful of co-authors, you probably won’t have to perform too many merges.
The most common situation is when someone else makes change while you are in the middle of yours.
(Typically you’ll find out about this either from an email notification, or an error message saying “Non fast forward updates were rejected” when you try to git push
.)
Most GUIs should have a good way of dealing with merges.
If you’re using a terminal instead, here are instructions:
Commit your changes when you are done editing. (But don’t push them yet. If you already tried to push them, and got an error message that’s OK.)
Run git pull
(or better still git pull --rebase
).
One of the following will happen:
Your editor is opened with a commit message saying something like:
Merge branch 'master' of ...
In this case, just save the file and exit your editor.
(In this situation if you had run git pull --rebase
instead of git pull
, you would not have the unfriendly Merge branch ...
shenanigans to deal with.)
Git exits with an error message saying something about conflicts. This means that some remote change conflicted with some local change you made. Resolve this conflict.
Git succeeds.
Push your changes back via git push
.
No matter what happened with the previous step, DO NOT forget this step.
Conflicts arise when more than one person edited the same part of the same file.
You might encounter it after doing a pull (via git pull
, git pull --rebase
) or a git merge
.
The status message should tell you what files are conflicted, and what you should do once you have “fixed the conflicts”.
You can fix these conflicts by opening these files in your editor, and searching for the conflict markers <<<<<<<
, =======
, >>>>>>>
.
Here’s what it will typically look like:
In 1875, Galton and Watson~\cite{WatsonGalton75} took up an investigation into the phenomenon of ``the decay of the families of men who occupied conspicuous positions in past times.'' <<<<<<< HEAD:paper.tex The problem, posed by Galton, was summarized by the Rev. H. W. Watson as follows. ======= The problem was summarized by the Rev. H. W. Watson as follows. >>>>>>> fe933fa:paper.tex
The text between <<<<<<<
and =======
is what you wrote, and the text between =======
and >>>>>>>
is what your co-authors wrote.
Edit it to your taste, remove the conflict markers.
Your conflict is now fixed.
Type git status
and follow the instructions.
(This will typically involving marking your conflicts as fixed using git add
, and the concluding the merge/rebase using git rebase --continue
or git commit
.)
Once you’re done, don’t forget to push your changes back.
Some GUIs might help you with merging, if you don’t like the above.
Alternately, you can also use git mergetool
to help.
Once you’re a more seasoned user of git
(on the terminal), here are a few tips that might help you.
This page has instructions showing you how to view differences between versions by words, lines or as a complied PDF using latexdiff.
git log
shows history and has many options.
Here’s a way to get colorful logs that are a bit easier to read.
Put the following in ~/.gitconfig
:
[alias] lg = log --format='%w(72,0,8)%C(auto)%h%d %s' lga = log --date=short --format='%w(72,0,8)%C(auto)%h %C(green)%cd \ %<(20,trunc)%aN%C(auto)%d%n%w(72,8,8)%s'
Now git lg
will show you a brief log, and git lga
will show you a brief log with authors.
The outputs look like this:
> git lg -5 0caf6bf (HEAD -> master) Avoid md.reset() when processing links 50bbc70 (origin/master, origin/HEAD) Used localhost for smtp. 95826b7 Fluids WG b47d349 Delete unused files in output b4a8b5d Added stochastic nucleation paper with Dan > git lga -5 0caf6bf 2016-12-11 Gautam Iyer (HEAD -> master) Avoid md.reset() when processing links 50bbc70 2016-11-12 Gautam Iyer (origin/master, origin/HEAD) Used localhost for smtp. 95826b7 2016-11-11 Gautam Iyer Fluids WG b47d349 2016-11-11 Gautam Iyer Delete unused files in output b4a8b5d 2016-10-25 Gautam Iyer Added stochastic nucleation paper with Dan
If you’re using git in a Dropbox folder that you never share with anyone else, then you can “just do it” and nothing should go wrong. If however, you plan to share the folder with co-authors, you should be careful. Here are instructions on how to do this safely.
If you use git
, but your co-authors don’t you can still get many benefits of git
when merging changes.
This will also avoid fiascos where your co-author edits an older version of the file, and silently overwrites your changes.
The trick to using git
in this situation is to find the commit the co-author based his changes on, and create a branch for these changes.
git
provides a way to do this, but requires some work to set up:
Edit (or create) .gitattributes
and add the line
*.tex text ident
Add a line containing $Id$
to your LaTeX files.
For instance,
% DO NOT EDIT -> $Id$ <- DO NOT EDIT
On checkouts (not checkins), git
will replace this with the SHA1 sum of the blob identifier.
Install git-ident.
Install the post-commit hook from git-ident
:
cd .git/hooks ln -s /path/to/git-ident/post-commit
Now edit and commit your changes as you normally would.
When you commit your changes, you’ll notice that the $Id$
token has been replaced with $Id: 987547... $
.
Share this file with your co-author (say over Dropbox, as described here).
When they are done making changes and send it to you, run
git-find-commit.pl file.tex
(git-find-commit.pl
is supplied with git-ident that was installed earlier.)
This will output the commit hash of the file your co-author based his changes on.
If this is what HEAD
points to, then he made changes based on your latest version, and you can just save his version over yours and you’re good to go.
If not, he made changes based on an earlier version (say ffffff
).
To merge it use
git checkout -b coauthor-v1 ffffff # Save his file over yours git commit --author 'Co Author <who@doesnt.use.git>' git checkout master git merge coauthor-v1
This way you keep the whole history in your git repository, and are guaranteed that your co-author hasn’t accidentally used an old version and overwritten your changes.
Git, of course, is much more powerful than the simple use case described above. Here are links to more information:
Collaborating with LaTeX and git (from the ShareLaTeX blog).
Collaborative Writing of LaTeX Documents (a wiki book describing collaborating with LaTeX in general, and not just with git).
The Pro-Git book (a comprehensive introduction to git).