How to use git

1 What is git?

Distributed version control system, which has basically become the de facto standard in open source projects. Developed in 2005 by Linus Torvalds in order to replace the closed source Bitkeeper software, which was in use to maintain the development of the Linux kernel.

From Wikipedia:

"git" can mean anything, depending on your mood.

  • Random three-letter combination that is pronounceable, and not actually used by any common UNIX command. The fact that it is a mispronunciation of "get" may or may not be relevant.
  • Stupid. Contemptible and despicable. Simple. Take your pick from the dictionary of slang.
  • "Global information tracker": you're in a good mood, and it actually works for you. Angels sing, and a light suddenly fills the room.
  • "Goddamn idiotic truckload of sh*t": when it breaks.

Main features:

  • git saves versions as hashed diffs
  • you always have the full history with all versions and branches in your local copy of the repository
  • branches are cheap, fast and encouraged!

2 Before you start

Obviously, you will need to have git installed. Get it from the git official homepage, which also has a link to a complete book on git.

  • configure git:
  • settings will be stored in $HOME/.gitconfig
git config --global user.name "Michael Olberg"
git config --global user.email "michael.olberg@chalmers.se"

2.1 Getting help

git help <verb>
git <verb> --help

3 Create your first repo

3.1 From an empty directory

git init foo

which is equivalent to

mkdir foo
cd foo
git init

3.2 From a directory with files

cd bar
git init
git add -A   # add all files

4 Working with your repository

Git distinguishes between the following states of a file, (see here):

  • untracked: a file not being part of your repo, e.g. a new file
  • unmodified: a committed, unmodified file
  • modified: a file in your repo which has been modified
  • staged: a file which has been added (staged) but not comitted, yet.
touch foo
git status      # will show foo as untracked
git add foo
git status      # will show foo tracked (and staged) but not committed
edit foo
git status      # will show foo as not committed *and* modified
git commit -m "add file foo"
git status      # the old version is now committed, the edited version is unstaged

4.1 Get the status

The status command typically suggests to you what you should be doing next, or, alternatively, how you can revert your last step.

git status
git status -uno   # useful if you have lots of untracked files

4.2 Logging

To see the history of your commits

git log
git log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short

You could create an alias for the above command

git config --global alias.hist 'log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short'
git hist

4.3 Tagging

Tag your versions, rather than referring to them by commit hash

git tag v1.0     # a light weight tag
git tag -a v1.2 -m "my new version v1.2"  # an annotated tag with commit message

5 Branching

5.1 Create a branch

git branch              # show which branches exist and which one we are on
git branch newfeature   # create a new branch ...
git checkout newfeature # ... and start working on it
edit file1
git add file1
git commit -m "add file1"
git diff master         # show differences wrt other branch
git checkout master
git merge newfeature

5.2 Keep a .gitignore file

A git repository is mainly for ASCII files, so put all binary files in .gitignore, so you won't commit by mistake:

A typical .gitignore file might look like

*~
*.o
*.a
*.so
*.pdf
dist/
.DS_Store

Don't forget to add the .gitignore to your repository:

git add .gitignore
git commit -m "add .gitignore file"

6 Working with remote repositories

Remote repositories can be

  • on github, gitlab, bitbucket, gogs, … all with basically the same web interface
  • a different directory and/or machine (in the latter case a git server is running)
  • you will typically have to get an account on the web site where you want to host your project

6.1 Create the remote repository first

  • Follow the instructions of the web interface to create a new project
  • typically choose to add README.md and .gitignore file
  • it is recommended to add a LICENSE file
  • on your local machine clone the repository
git clone https://whatever/foo.git
cd foo

6.2 Create the local repository first

  • Follow the instructions of the web interface to create a new project
  • typically do not add any default files

On your local machine

git remote add https://whatever/foo.git
git push -u origin master
git push --tags    # also push tags if you have some

6.3 Pull requests

This is a feature of web based git repositories, not really git itself.

  • go to somebody else's repository on github (or similar) and click fork, this will create a copy of the repository on github but now owned by you.
git clone https://github.com/molberg/tool.git
cd tool
git branch mychange
git checkout mychange
edit <file>
git add file
git push -u origin mychange
  • your modification should now show up as a pull request in the repository of somebody else

7 Examples

7.1 Working on the command line

Example: fakeobs

tar xzvf Fakeobs_v0.4.tar.gz
cd Fakeobs_v0.4
git status

This will tell us that the current directory is not under git version control. Initialize it and remove files that won't be part of the repository

git init
rm *.pyc mytasks.py fakeobs_cli.py fakeobs.py
echo mytasks.py > .gitignore
echo fakeobs_cli.py >> .gitignore
echo fakeobs.py >> .gitignore
echo '*.pyc' >> .gitignore
echo '*~' >> .gitignore
git add fakeobs.xml INSTALL LICENSE task_fakeobs.py .gitignore
git status
git commit -m "initial commit"
git status
git log

Make your first changes. Rename INSTALL to README.md and reformat to markdown syntax.

git mv INSTALL README.md
# edit README.md
git add README.md
git commit -m "rename INSTALL to README.md and reformat"

Make a branch and fix Python syntax

git branch   # list all branches
git branch autopep
git checkout autopep
# reformat task_fakeobs.py
git add task_fakeobs.py
git commit -m "reformat using autopep"
# maybe do some testingh on branch autopep
git checkout master
git merge autopep
git branch -d autopep    # autopep branch no longer needed

7.2 Working with VS Code

Example: checkres

We will start with a casa 5 version already hosted on github and convert to casa 6, following a procedure outlined in the casa 6 documentation for buildmytasks. I will be using a python virtual environment with casatools and casatasks installed:

python -m venv casa6
source casa6/bin/activate
pip install --upgrade pip
pip install numpy
pip install scipy
pip install matplotlib
pip install --index-url https://casa-pip.nrao.edu/repository/pypi-casa-release/simple casatools
pip install --index-url https://casa-pip.nrao.edu/repository/pypi-casa-release/simple casatasks
pip install --index-url https://casa-pip.nrao.edu/repository/pypi-casa-release/simple casadata
pip install flake8

Now, inside the virtual environment, prepare the casa 6 version, starting with the existing github repository for the casa 5 version. Create a new branch for this.

git clone git@github.com:onsala-space-observatory/checkres.git
cd checkres
git branch casa6
git checkout casa6

Now continue in codium (or code).

codium .
  • select virtualenv for casa6
  • open file task_checkres.py
  • run linter on code and fix print statement
  • in terminal:
python /home/michael/Python/casa6/buildmytasks --upgrade checkres.xml
rm checkres.xml.bak
mkdir private
git mv task_checkres.py private/
echo '__name__ = "checkres"' > __init__.py
echo '__all__ = [ "checkres" ]' >> __init__.py
echo 'from .checkres import checkres' >> __init__.py

In VS code:

  • update installation instructions
  • stage all files
  • commit changes

Finally, push branch to github:

git push origin casa6