We have an ATLAS cheat sheet that gives the most important git commands and terms that we use in ATLAS code development. Keep this by your side!
On the 17th December 2018, ATLAS updated the Athena repository to make it public and open-source. If you are an ATLAS member and have forks or clones from before that date, please look at the instructions on the twiki
A few useful aliases that you can add to your ~/.gitconfig
:
[alias]
# Nicely formatted history
hist = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short
lg = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all
# Find/show merge request for commit on current branch (http://stackoverflow.com/q/8475448/)
find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 | uniq -f1 -d | sort -n | tail -1 | cut -f2'"
show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'"
# Fetch an open MR
fetch-mr = "!sh -c 'git fetch $1 merge-requests/$2/head:mr-$2' -"
If you want to avoid switching between your source and build directories, you can tell git where your working directory and repository resides by setting:
export GIT_WORK_TREE=/path/to/my/git/repo
export GIT_DIR=${GIT_WORK_TREE}/.git
All git commands (e.g. git diff
) will then operate as if you had executed
them in your working directory even if your current directory is different. Note
the above is a special case of using multiple work directories with the same git
repository. For further details see
Git Loves the Environment
and git-worktree.
A plain git diff -- PATH
shows the difference of the currently checked out files
against the copy that is staged (or last commit) for PATH
. It is very common
to diff against a commit ID or a tag and as ATLAS makes tags for each release
it is easy to diff changes between the current version and
a release tag:
git diff release/21.0.8 -- Tools/PyJobTransforms
To show the difference between two releases use:
git diff release/21.0.1..release/21.0.8 -- Tools/PyJobTransforms
git diff nightly/21.0/2017-05-05T2130..nightly/21.0/2017-05-06T2130 -- MagneticField
Use git diff --name-only
to only show the file names that changed.
GitLab also has web-based diff
feature that can be useful for look at a limited number of changes, e.g. between
two nightlies (it does not allow to filter on a PATH though).
git revisions --help
gives more information on how to specify
revisions:
HEAD
has the obvious meaning^
means parent of, so HEAD^
means the commit before
current HEAD
~N
means the Nth ancestor, so HEAD~10
means the 10th commit
before HEAD
A..B
is equivalent to A B
in the above examplesIf you replace diff
with log
in the above commands, you will see the
commits and their log messages.
git log # from HEAD backwards
git log release/21.0.1..release/21.0.8 -- Tools/PyJobTransforms
There are many options controlling how much to show, e.g, --oneline
or --pretty=format:...
(see the examples above).
git show [commit id]
shows both the commit log and the diff with respect to
the previous version.
If you want to apply (“cherry-pick”) an entire merge request (which may consist of several commits), to your local branch use one of the following two options:
git fetch upstream
git cherry-pick -m 1 HASH
where HASH
is the merge commit hash that you can find on the GitLab MR page
(e.g. 934a7995
, click on the clipboard icon to copy/paste it):
For each open MR, GitLab stores a special reference in the main repository under
refs/merge-requests/MRID
where MRID
is the merge request ID (e.g. 42420).
So you can simply fetch the branch from there (instead of having to add the developer’s fork as a remote):
git fetch upstream merge-requests/MRID/head:mr-MRID
git merge mr-MRID
See the
fetch-mr
alias above as a convenient shortcut for the first command.
One of the most useful forms of rebasing, used for squashing commits and rewriting commit messages, is the interactive rebase. To do this run
git rebase -i HEAD~N
Where git will keep commit HEAD~N
commit the same, but then rebase everything else
from here up to HEAD
; HEAD~N
is the Nth ancestor of HEAD
(be aware
that if there are merge commits in the range you specify you might well get more
commits included that you expect, git log --oneline HEAD~N..HEAD
will help, but
it is strongly discouraged to rebase across merge commits).
Now in your editor a page will open, showing every commit that will be part of the
rebase along with what will happen to it (the default is pick
meaning
keep this commit as is) and the one line commit message.
Do make sure that your
EDITOR
environment variable is set to an editor that you know how to use.
To merge a commit with its parent, change pick
to squash
(or just s
); if
you choose fixup
instead then the commit message for the fixed-up commit
will be discarded. In both cases you will have the chance to rewrite the commit
message for the merged commit. To just rewrite a commit message change the command to reword
.
The descriptions of the other command options are pretty clear.
When you save and exit your editor git will execute each of the rebase commands in turn, producing a new commit history from the starting point.
A much more extensive discussion of these options is in the git tools documentation.
If you get strange cmake errors e.g.
undefined reference to `pthread_create'
then it’s likely that you have:
testarea = <pwd>
in an .asetup
file, and you also ran asetup inside the athena/
directory.
You could remove testarea
, delete the extraneous files (use git status
to find what was added) and re-run. However we instead recommend running
asetup
in the top-level directory (i.e. the directory which contains athena/
),
as this means you don’t need to modify your configuration but also avoids
asetup
creating unnecessary local .asetup
files.