wiki:WorkingWithGithub
Last modified 5 years ago Last modified on 08/20/13 08:55:28

NB This page is a guide for using git and github. There are many ways you can use git and this page describes a reasonable workflow that's hopefully not too complicated. Variations on the ideas here are allowed; however, you are responsible for making sure what you're doing works.

What is github

github is a central repository for projects to host content that they manage using git. dCache has a group-owned account on github, where we store a number of repositories.

This page contains some essencial information on getting started. Is cannot include all possible details, so you are encouraged to learn more elsewhere.

Here are some useful places for more information:

Get it started

Here are some steps that all developers will need to do:

  1. configure your name: git config user.name "First Last"
  2. configure your email address: git config user.email "first.last@example.org"
    Use your real name when committing, e.g. no nick names.
  3. configure ReviewBoard location: git config --global reviewboard.url http://rb.dcache.org
  4. create a ~/.gitmessage.txt file with:
    module: summary line
    
    what happened
    
    Ticket: #number
    Acked-by: 
    Target: trunk
    Require-book: no
    Require-notes: no
    
  5. set the commit message template git config --global commit.template ~/.gitmessage.txt
  6. clone the github repository: git clone https://github.com/dCache/dcache.git
    This will create a directory 'dcache' containing the git cloned repository.

How do we use github

There are several development models that git (and github) can support. The model described here is perhaps the simplest for people already familiar with traditional SCM systems, like CVS and SVN.

The github repo is a central repository that contains various source code, similar to how we used to use SVN.

General policy:

  • All development work is done on non-master branches,
  • Only change master branch once code has passed review and is ready to push to github

Example development cycle

This example is to fix a bug in gPlazma. The development branch name is fixing_gPlazma_NPE. In general, you may choose any (valid) name for the development branch (man git-check-ref-format for details), but a meaningful name is recommended.

Here are the steps to edit dCache code:

  1. Change current-working-directory to somewhere within the local clone: cd ~/git/dCache
  2. Create a local branch based on master and switch to it: git checkout -b fixing_gPlazma_NPE master

  3. Develop the patch as normal: edit the code, test the changes, add unit-tests, etc.

    Git encourages frequent commits to the branch as these commits are local and do not affect anyone else.
    • Option 1: commit all modified and deleted files, but ignore any new files:
      1. commit all modified and deleted files: git commit -a

    • Option 2: commit all modified and deleted files and selected new files:
      1. stage new-file-1 and new-file-2: git add path/to/new-file-1 path/to/new-file-2
      2. commit all staged, modified and deleted files: git commit -a

    • Option 3: commit selected files
      1. stage file1, file2 and file3: git add path/to/file1 different/path/to/file2 another/path/file3
      2. unstage file3, which was staged by mistake: git rm --cache another/path/file3
      3. delete file4 and stage this deletion: git rm path/to/file4
      4. rename file5 as file6: git mv path/to/file5 path/to/file6
      5. commit all staged activity: git commit

    Additionally: keeping development branch up-to-date with commits to github's master branch:
    1. switch to master branch: git checkout master
    2. fetch any updates: git pull
    3. switch back to development branch: git checkout fixing_gPlazma_NPE
    4. reposition local changes after updates from master: git rebase master

  4. Post the proposed changes to ReviewBoard.

    1. (if not already done) switch to development branch: git checkout fixing_gPlazma_NPE
    2. either using post-review, one of:
      1. generate the initial post

        post-review --guess-description --summary="your summary here" --testing-done="how did you test" --parent=master
        Be aware of the ReviewBoard message format. If you are working on your own fork of a repo and you wish to post-review you can use the e.g. --repository-url=git@github.com:dCache/dcache.git In this case it would create the review for the dcache repo.

      2. Update an existing review (review ID 2013 in this example)

        post-review -r 2013 --parent=master

      3. You can also define most properties in a file called .reviewboardrc in the repository directory:
        REPOSITORY = "git@github.com:dCache/dcache.git"
        PARENT_BRANCH = "master"
        TARGET_GROUPS = "all"
        GUESS_FIELDS = True
        OPEN_BROWSER = True
        
    3. or generate diffs and manage ReviewBoard entry manually.
  5. If the review requires changes, loop back to step 3.

    Now we "commit" the patch to github.

  6. Switch to master branch: git checkout master
  7. Update from github: git pull
  8. Apply work: git merge --squash fixing_gPlazma_NPE
  9. If there are any conflicts from the merge command, fix them and re-test.
  10. Commit these changes to the local master branch: git commit -a

    The commit message must follow the commit message format.
    BE VERY CAREFUL, THE DEFAULT MESSAGE IS NOT APPROPRIATE

  11. Push these changes up to github: git push

  12. The push may fail if someone "commits" a patch to github between steps 7. and 11. if that happens then:
    1. pull in new changes: git pull
    2. resolve any problems from the implicit merge and re-test
    3. loop back to step 11.

Improve Bash/Zsh? Prompt for GIT

Both prompts will show the current branch and its status. The zsh one is a bit prettier,

  1. Have a look at this.
  2. Bash: Set your prompt to
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:'$Color_Off'$(git branch &>/dev/null;
    if [ $? -eq 0 ]; 
    then 
        echo "$(echo `git status` | grep "nothing to commit" > /dev/null 2>&1;
        if [ "$?" -eq "0" ]; 
        then  # @4 - Clean repository - nothing to commit
            echo "'$Green'"$(__git_ps1 " {%s}");
        else  # @5 - Changes to working tree
            echo "'$IRed'"$(__git_ps1 " {%s}"); 
        fi) '$Yellow$PathShort$Color_Off'\$ ";
    else # @2 - Prompt when not in GIT repo
        echo " '$Yellow$PathShort$Color_Off'\$ ";
    fi)'
    
    where
    Color_Off="\[\033[0m\]"       # Text Reset
    Green="\[\033[0;32m\]"        # Green 
    IRed="\[\033[0;91m\]"         # Red
    Yellow="\[\033[0;33m\]"       # Yellow
    PathShort="\w"
    

When your hammer is GIT, everything begins to look like a thumb

  • Never re-write the history if changes are pushed
  • Never enforce fast-forward on push, e.g. git push --force. Solve it with pull and merge