For short and to-the-point Git tutorials see e.g. here:
Git identifies the authors of commits by their email, so when you first use git on a new system, you have to tell it yours:
$ git config --global user.name "John Doe" $ git config --global user.email "email@example.com"
--global option puts this into your global
~/.gitconfig file, which applies to all your local git repos. Using
--local (the default) allows a per-repository setting.
The email you use should be the one associated with your DESY user account. That way, your commits are associated with your user profile.
To clone the main
scetlib repository, do
$ git clone ssh://firstname.lastname@example.org:7999/scetlib/scetlib.git
scetlib/of the current directory.
scetlib/.git/ directory. (The repo's main configuration lives in
scetlib/.git/config, which can be useful occasionally.
scetlib/directory itself serves as the working area. (It starts out containing the content of the default branch, typically either
The possible access methods and different repositories are described below.
We use a standard Git workflow, where all feature development happens in branches. Each module has its own branch with possible sub-branches for feature development. The integration happens through the develop branch.
Here is a summary of the conventions for branches and their relations
|Branch||Purpose||Originates from||Merges into|
|Public access for stable releases, contains abridged (squashed) version of master|
|Critical fixes to stable releases|
|Integration of all features that will go into next release|
|Preparation for stable release|
|Development of core library|
|Main development for module 'xxx'|
|Development of 'feature' in module 'xxx'|
Below, we go through the most important git commands and their most relevant options.
All commands have additional options for special purposes or finetuning their behavior. There are also many additional commands. To see a detailed documentation for a command with a list of all options and usage examples, do
$ git help <command>
Git commands always act on the entire repository you are in, it does not matter in which directory you are inside your working area (this is a big difference to svn)
List of all branches (with the current branch highlighted):
$ git branch [-vv | -a | -avv]
-avvoption is the most useful. With
-ait shows both local and remote branches. With
-vv, for each local branch, it shows which remote branch it trackes and by how many commits it is ahead/behind.
Show the commit history on the command line:
$ git log [--oneline] [--graph]
--onelineonly the first line of each commit message is shown.
--grapha text-based graphical representation of the commit tree is included.
git logfrom the command line. A standard program coming with git is
gitk, which also shows the detailed changes.
in git are simply pointers to commits. Commits do not belong to (are "owned by") specific branches.
Switch to a branch to start working on it, in this example the
$ git checkout develop
develop(more precisely, the commit
develop, which makes it the "current branch" which many operations (commit, merge, etc.) are relative to.
origin/develop), this will automatically create a local branch
Create a new branch, say
feature-cool, and start working on it:
$ git checkout -b feature-cool [<start-point>]
<start-point>or if not given the current HEAD. It then switches to the new branch.
<start-point>is a remote branch, this sets up
feature-coolto track the remote branch.
The above is exactly equivalent to doing
$ git branch feature-cool [<start-point>] $ git checkout feature-cool
Rename or delete a branch:
$ git branch -m feature-cool feature-supercool $ git branch [-d|-D] feature-supercool
-doption only deletes the branch if it is merged with an upstream branch, i.e. if the commits are reachable from another branch.
-Doptions deletes the branch no matter what. This drops commits that are only on this branch and not reachable otherwise. (The commits are still present for a while and are only dropped during the next garbage collection. This means you can checkout and recover them if you know their commit id.)
Show the current status of the working tree and the commit staging area (also called the 'index'):
$ git status [--ignored]
--ignoredoption also shows all files that are being ignored by git.
git statusis your best git friend, since it also tells what and how to do next.
Register changes to be part of the next commit
$ git add <files> $ git add <path>
<files>or all modified/new files in the given
<path>to the commit staging area (also called the index). All modifications (not just new files) have to be staged before committing. Further modifications to already staged files have to be added again.
Unstage changes from the next commit
$ git reset <files> $ git reset <path>
<path>from the staging area, so this is the oppsoite of
git resetis rather powerful, so one has to be a bit careful. (When given a branch or commit it will operate on the entire commit.)
Commit staged changes:
$ git commit [--amend]
--amend, the staged changes are combined with the previous commit into a new commit which replaces the previous commit. This is very useful to fixup the last commit when some changes were forgotten or to fix a bug. However, see the warning on changing history below.
Convenient graphical tools for staging and unstaging, reviewing changes, and committing are
$ git gui & $ git cola &
Good commit messages are crucial for navigating the commit history, finding bugs, etc.
Write one line/sentence (in active present tense) with a short description of what the commit does.
The main purpose is to document the commit and the changes, not so much to discuss your reasons for doing so.
An often useful form is to give a bullet list with details:
Git has two different ways to combine the changes in different branches: merging and rebasing.
Merge changes from
<branch> since its history diverged from the current branch into the current branch (see
git help merge for details and examples)
$ git merge <branch>
git merge --abort, which returns the current branch to its pre-merge state.
<branch>is directly ahead of the current branch, so there is no fork in the history, the merge resolves as a so-called fast-forward merge. In this case, the current branch is simply updated ("fast-forwarded") to point at
<branch>without generating a separate merge commit.
Reapply changes of each commit of the current branch since its history diverged from
<branch> on top of
git help rebase for details and examples)
$ git rebase [-i] <branch or commit>
<branch>, appropriately merging each one with the existing changes in
git rebase --continueor abandonded with
git rebase --abort.
<branch or commit>is directly ahead of the current branch, it will simply be fast-fowarded.
-ioption triggers an interactive rebase. This allows the commits to be selected, combined, reordered, edited, etc. This allows to rewrite and reorder the history of the current branch by specifying a
<commit>to rebase against which is in the direct past of the current branch, such as
Rebasing keeps the commit tree linear, which makes future merges easier (e.g. more likely to resolve as fast-forward). However, see the warning on changing history below. If possible/allowed, always use rebase
Merging preserves the exact commit and merge history, including the historical existence of branches and connection between different branches. Only use merge
Throw away changes:
$ git reset --hard <branch or commit>
HEAD~, and similarly
HEAD~2is the current commit's grandparent. This also works for branches and commit ids, so
develop~3refers to the commit 3 steps back from the commit the
developbranch points at.
are also just pointers to locally known commits. Their difference to local branches is in their different behaviour.
In git, updating your repo with new changes from a remote repo (the equivalent of
svn update) is a two-step process: First you download new commits, then, if needed, you combine those with your current work using rebase or merge, just like combining changes between local branches. Separating the two steps provides much more control over nontrivial merges or conflicts, which makes handling them much easier.
Download upstream commits from the remote repo:
$ git fetch [-p]
git checkout origin/<branch>. (This does not create a local
origin/<branch>, but simply checks out the commit.)
The -p option removes any remote branches that do no longer exist on the remote repo.
Incorporate upstream commits with your local ones:
$ git [i-] rebase [origin/<currentbranch>]
<currentbranch>and is setup to track the remote branch
<origin/<currentbranch>(which is the standard case), then the remote branch is automatically supplied and can be omitted.
Merge upstream changes with your local ones:
$ git merge [origin/<currentbranch>]
Single Step Pull:
$ git pull [--rebase]
--rebaseoption fetch and rebase. (So it behaves similar to
Upload your changes to the remote repo:
$ git push [--all] $ git push -u origin <newbranch>
--allfor all local branches) to the remote repo together with updating the remote branches.
-uis to setup the local branch to henceforth track the newly created remote branch.
And finally, here is the promised
Commits that have been pushed become public history and once someone has pulled them they become shared history. Shared history should normally not be changed, which means:
The reason is that anyone having pulled the history, by pulling again their remote branch will now point to the changed history but their corresponding local branch will still point to the previous history. This can be confusing and requires them to reset the local branch to the new remote one. If someone already made changes, they will have to rebase their changes onto the new remote branch.
The repositories are hosted on DESY Stash.
(master, develop, core, module branches)
clone/pull: all developers
browse/comment: all developers
push: module developers only
|stores module data|
|public releases (stable branch)||clone/pull/browse: public|
|read/write: module developers only|
There are different methods for accessing the Stash repositories summarized here:
|Method||How to access||Operations|
|ssh||clone, pull, push|
|https||clone, pull, push|
|web interface||browse, comment, pull request|
There are three ways to authenticate with Stash:
Here is a summary of allowed operations for the different levels of authentication:
|clone, pull, browse public|
|push to unrestricted branch||/||( via ssh)|
|push to write-restricted branch||/|
Here / means that access can be configured for specific users if needed.
ssh is the recommended way for command-line access, since it uses ssh keys and no passwords are required.
To configure authenticated ssh access, go to your Stash profile and install your public ssh key. When accessing the git repos via ssh using a so-installed ssh key, the Stash server automatically authenticates and associate the access with your Stash account.
For unauthenticated ssh access, your public ssh key can be installed directly in the repo (you have to email it to Frank). The advantage is that this works without requiring a Stash account, but it has some limitations as shown in the table above.
Some networks block port 7999. In this case https is the only fall-back option.