-
Notifications
You must be signed in to change notification settings - Fork 39
Git
MAD-X has migrated from SVN to git version control.
For users not familiar with git, we provide some references and a cheat sheet that will cover the most common use cases:
- Getting help
- Git concepts
- Overview (most of what you will need in 5 minutes)
In more detail:
I can't stress this enough: git has among the best help system of all command line tools that you will ever see:
git help git help COMMAND
Try it now:
git help commit
Note that git also has great official online resources such as tutorials and comprehensive documentation that you should absolutely refer to in case of problems. These will provide a much better insight over the tool than the quick cheat sheet we will provide here.
- book
- documentation
- crash course for SVN users
-
git help COMMAND!
This following is a non-comprehensive list of the most important conceptual differences between SVN and GIT. It is not strictly required to work with git but understanding it will make your life a lot easier down the road:
- git history is structured as a DAG (directed acyclic graph) of commits rather than a linear series of revisions. This is great to represent the graph structure due to branching.
- git commits are labeled by their SHA1 hash rather than a revision number.
- a branch or tag in git is just a pointer to a commit, in SVN a branch or tag is a copy of a directory. Branching and tagging in git are extremely lightweight operations (creating a pointer).
- git has an index or staging area that determines what goes into the next
commit. Changes can be added with very fine-graded control to the index. If
you type
git diff, you can see the changes in the current working directory versus the current index. If you typegit diff --cached, you can see the changes that have been added to the index versus the currentHEAD. - git is a distributed VCS, which means that it has a very flexible approach to working with no or many other parties (see Remotes) – as opposed to SVN where you are usually bound to exactly one upstream SVN server.
- The recommended work-flow in git is that everyone operates on their own repository rather than working simultaneously on the upstream repository as in SVN. This makes it a lot easier to deal with merge conflicts.
- git checkouts are fully-fledged forks of the entire repository including its history. They can function fully independent of the original repository.
- That's why most git operations never touch the network, and are therefore
very fast operations that don't require a password. This is different from
SVN where even simple operations such as
svn logmay require entering a password. - In fact, git can be used without any local or remote server. You can turn
arbitrary directories into git repositories by typing
git initand later add a remote URL if you want to share or backup your changes.
More about git internals:
-
HEADis the symbolic name of the commit that is currently checked out. - git repositories are a collection of objects stored inside the
.gitrepository. - git objects consist of some blob of data and are referenced by their SHA-1
hash. The most important objects and their data blobs are:
- file: the file content
- tree: list of references to files and sub trees
- commit: commit message; reference to the file tree; author, date and other metadata
- git branches are just pointers (references to) to commits.
- git has a garbage collector that can delete objects if they become unreferenced for too long (more than one week). Objects referenced directly or indirectly by a branch or tag will never be deleted by git.
- As long as objects are not deleted they can always be checked out or
queried otherwise.
git reflogis a useful tool to get the hashes of commits that were deleted by accident.
The recommended work-flow in git is that everyone operates on their own repository rather than working simultaneously on the upstream repository as in SVN. This makes it a lot easier to deal with merge conflicts.
Do once the following:
-
configure your name and email:
git config --global user.name "Full Name" git config --global user.email "[email protected]"
If you want, add some more useful Settings and aliases to your
~/.gitconfig. -
fork the MAD-X repository onto your own github username (see Forking).
-
clone your fork and add the official MAD-X repository as upstream:
git clone [email protected]:USERNAME/MAD-X cd MAD-X git remote add upstream [email protected]:MethodicalAcceleratorDesign/MAD-X
In order to contribute patches, do the following:
-
make sure your upstream is up-to-date and create a branch for your new feature/bugfix. Most of the time it's best to branch off the upstream master:
git fetch upstream git checkout -b feature upstream/master git push -u origin feature
(Note that the
fetchcommand just fetches data to be stored in the.gitfolder but never interferes with your local checkout.) -
edit files, build and test:
vim src/twiss.f90 make madx-linux64-gnu make tests
-
add relevant changes to the INDEX:
git diff # check the diff to be added git add src/twiss.f90 # add complete file(s) git add src/twiss.f90 -p # select chunks within file to add
-
inspect the status and commit added changes to your local repository:
git status # check which files will be committed git diff --cached # check the diff to be committed git commit -m "Implement awesome feature XYZ"
-
check your commit log:
git log # commits of current branch git log --all --graph # all branches
-
if/when you want, upload your changes to github:
git push
-
create a pull request on the github site
-
if there are conflicts with the upstream master:
# if you have uncommitted changes (or commit!): git stash # pull in the upstream master: git pull upstream master # manually resolve conflicts, relevant sections enclosed by # "<<<<", "====", ">>>>>" lines: vim src/twiss.f90 # add and commit conflict resolution: git add src/twiss.f90 git status git commit git push
-
if you want to reorder/join/drop commits or you have a branch that is based on an old version of master and you want to move (reapply) the commits onto the new master (or another branch):
git fetch upstream git rebase -i upstream/master
In certain situations, you might need:
git rebase -i --onto upstream/master BASE_POINT BRANCH_NAME
Where BASE_POINT specifies the parent of the first commit to reapply onto the upstream master.
For users without github account or SSH key:
git clone https://github.com/MethodicalAcceleratorDesign/MAD-X
For users with github account and SSH key:
git clone [email protected]:MethodicalAcceleratorDesign/MAD-X
Note that (unlike SVN) cloning the repository fetches the entire history and creates a fully-fledged repository on which you can work and commit locally without having to push your changes to the upstream repository.
If you plan to contribute, you should fork the repository:
Login to your github account and fork the MAD-X repository to your own account (using the button somewhere in the upper right). I recommend accessing your fork via SSH (See Adding an SSH key).
Now clone your fork using:
git clone [email protected]:USERNAME/MAD-X
If you had already cloned the upstream repository, you can add your own fork as an additional remote:
git remote add myfork [email protected]:USERNAME/MAD-X
As a distributed version control system, git features a very flexible approach to working with multiple parties. This is captured by the concepts of remotes which specify the URLs (or filesystem path) of remote repositories.
List your remotes:
git remote -v # -v stands for verbose
Add a new remote and fetch data into your .git folder (does not change the
current working directory):
git remote add NAME URL git fetch NAME
Rename an existing remote:
git remote rename OLD NEW
Delete a remote:
git remote rm NAME
For example, if you have cloned the upstream repository, created a few commits, then forked the repository and you now want to add your fork in order to push commits there, you can add it as a new remote like this:
git remote add myfork [email protected]:USERNAME/MAD-X git fetch
OR:
git remote rename origin upstream git remote add origin [email protected]:USERNAME/MAD-X git fetch origin
If you plan to contribute, I recommend accessing the repository via SSH rather than HTTPS. This means that you will not have to enter your password on every push. If you haven't already, create an SSH key:
ssh-keygen -b 4096
You can leave the password blank to store the key unencrypted (!) to your home folder. In this case, you won't need to enter password when pushing (in my opinion, if someone gets access to your harddrive, all your data is compromised anyway). If you dislike storing the key without further protection, you can enter a password and consider
Copy the SSH public key (cat ~/.ssh/config/id_rsa.pub) and add it on your
github settings page.
You may find it convenient to add a few basic aliases and settings to your
~/.gitconfig. I encourage you to try and find out how these aliases work
and what they do:
[core]
editor = vim
excludesfile = /home/thomas/.gitignore_global
filemode = true
[alias]
co = checkout
cp = cherry-pick
st = status
re = remote -v
# fixup current index to the previous commit
amend = commit --amend
amenda = commit --amend -a
# merge and create a structural merge-commit (no fast-forward)
mm = merge --no-ff
# useful diffs:
cdiff = diff --cached
wdiff = diff --word-diff=color
wcdiff = diff --cached --word-diff=color
# log with graph structure:
alog = log --graph --all --format=cmedium
# unstage (remove from index) some files:
unstage = reset HEAD --
# checkout pull request by issue number (and remote name):
copr = "!f() { git fetch -fu ${2:-origin} refs/pull/$1/head:pr/$1 && git checkout pr/$1; }; f"
# enable/specify colors:
[color]
ui = true
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "diff"]
meta = yellow bold
frag = magenta bold
old = red bold
new = green bold
[color "status"]
added = yellow
updated = green
changed = magenta
untracked = cyan
branch = green bold
[diff]
tool = vimdiff
[difftool]
prompt = false
# required for the nice graph log:
[pretty]
cmedium =\
%C(yellow)%h%C(cyan)% an %C(green)(%ar)%C(red)%d%n\
%C(white)%s%n\