This is an old revision of the document!


Git Setup and Configuration

This article explains how to perform version control using Git (Linux or Windows server) and TortoiseGit (Windows client).

Installation

Install git server and client in Ubuntu Linux:

$ sudo apt-get update
$ sudo apt-get install git

Install git server and client in Windows:

Configuration

Customize Git environment (Git Client) to include developer's name and email address:

  • In bash: Log in as end user (eg. jdoe), and add global configuration items:
    $ git config --global user.name "John Doe"
    $ git config --global user.email "jdoe@example.com"

    View the configuration:

    $ git config --list

    Edit the configuration:

    $ vi ~/.gitconfig
  • In Windows Explorer, right-click on a folder, and select “Tortoise Git” > “Settings”. Enter user information (name, email).
Repository Setup (directory under Version Control)
  • Create a directory for a project repository: Eg: For a calculator project, D:\proj\calc or /home/jdoe/proj/calc
  • Create Repository:
    • In Windows Explorer, right-click on folder to be repository. Select “TortoiseGit” > “Create Repository here”. Eg: D:\proj\calc\
    • In bash:
      $ cd /home/jdoe/proj/calc
      $ git init
  • Add settings to Git (by creating GitAttributes file) to avoid EOL character normalization and conversion: (IMPORTANT: Perform these steps BEFORE adding files to repository!)
    • In files [projname]/.git/info/gitattributes or [projname]/.gitattributes, comment out the following:
      #* text=auto''
      #* text eol=lf
    • In file [projname]/.git/config, add this:
      [core]
        autocrlf = false
        ...
    • Optionally, if files were added already, reset index before adding more files:
      $ rm .git/index            # Remove the index to force git to re-scan the working directory
      $ git reset                # Unstage files
      $ git status               # Show files that will be normalized
      $ git add -u               # Only add modified content of files already being tracked (not new)
      $ git add .gitattributes   # Add .gitattributes file to repository
  • Create or copy source code files to project directory. Eg:
    $ cp *.cs /home/jdoe/proj/calc
  • Stage files (begin tracking files). Add files to Git:
    • In Windows Explorer, right-click on project folder or file to be added to the repository. Select “TortoiseGit” > “Add”.
    • In bash:
      $ git add *.cs
      $ git add LICENSE.TXT
  • Commit files to repository:
    • In Windows Explorer, right-click on project folder. Select 'Git commit: > “master”'.
    • In bash:
      $ git commit -m "Initial repository commit"
Setup for EOL Normalization

When adding and committing files to Git, EOL characters get normalized, ie. translated to Git's default, which is [LF]. You can specify how to translate it (or not translate it at all).

Git checks the [projname]/.gitattributes file first, and if nothing matches there, it drops back to the local and system wide settings, such as found in [projname]/.git/config.

How core.autocrlf works:

core.autocrlf=true     core.autocrlf=input       core.autocrlf=false

       repo                     repo                    repo
    /        \               /        \              /        \
crlf->lf    lf->crlf     crlf->lf       \          /            \      
 /              \        /                \      /                \
push            pull    push              pull  push              pull

End-of-line marker:

  • crlf: win-style .
  • lf: unix-style.
  • cr: mac-style (not affected for any of three options above).

In file [projname]/.git/config, under [core]:

  • autocrlf = true, if you have unix-style lf in one of your files (= RARELY).
  • autocrlf = input, if you have win-style crlf in one of your files (= almost ALWAYS).
  • autocrlf = false, if no EOL normalization is wanted.
GitAttributes file
  • Create a file in [projname]/.git/info/gitattributes, or a [projname]/.gitattributes with the following:
    # Define the line ending behavior of the different file extensions
    # Set default behaviour, in case users don't have core.autocrlf set (comment out to disable).
    # Auto eol normalization for text files:
    #* text=auto
    # EOL character for normalization:
    #* text eol=lf
     
    # Explicitly declare text files we want to always be normalized and converted
    # to native line endings on checkout.  (Use 'text')
    #*.php text
    #*.default text
    #*.ctp text
    #*.sql text
    #*.md text
    #*.po text
    #*.js text
    #*.css text
    #*.ini text
    #*.properties text
    #*.txt text
    #*.xml text
    #*.yml text
    #.htaccess text
     
    # Disable normalization and conversion for these files (use '-text'):
    *.php -text
    *.default -text
    *.ctp -text
    *.sql -text
    *.md -text
    *.po -text
    *.js -text
    *.css -text
    *.ini -text
    *.properties -text
    *.txt -text
    *.xml -text
    *.yml -text
    .htaccess -text
     
    # Declare files that will always have CRLF line endings on checkout.
    *.bat eol=crlf
     
    # Declare files that will always have LF line endings on checkout.
    *.pem eol=lf
     
    # Denote all files that are truly binary and should not be modified.
    *.png binary
    *.jpg binary
    *.gif binary
    *.ico binary
    *.mo binary
Working with Git

Create Repositories

Start a new repository or obtain one from an existing URL.

$ git init [project-name]   # Creates a new local repository with the specified name.
$ git clone [url]           # Downloads a project and its entire version history.

Make Changes

Review edits and craft a commit transaction

$ git status          # Lists all new or modified files to be commited
$ git add [file/dir]  # Snapshots the file in preparation for versioning
$ git reset [file]    # Unstages the file, but preserve its contents
$ git diff            # Shows file differences not yet staged
$ git diff --staged   # Shows file differences between staging and the last file version
$ git commit -m "[descriptive message]"   # Records file snapshots permanently in version history

Group Changes

Name a series of commits and combine completed efforts

$ git branch                    # Lists all local branches in the current repository
$ git branch [branch-name]      # Creates a new branch
$ git checkout [branch-name]    # Switches to the specified branch and updates the working directory
$ git merge [branch]            # Combines the specified branch’s history into the current branch
$ git branch -d [branch-name]   # Deletes the specified branch  

Refactor Filenames

Relocate and remove versioned files

$ git rm [file]           # Deletes the file from the working directory and stages the deletion
$ git rm --cached [file]  # Removes the file from version control but preserves the file locally
$ git mv [file-original] [file-renamed]  # Changes the file name and prepares it for commit  

Suppress Tracking

Exclude temporary files and paths *.log, build/, temp-*. A text file named .gitignore suppresses accidental versioning of files and paths matching the specified patterns.

$ git ls-files --other --ignored --exclude-standard  # Lists all ignored files in this project  

Save Fragments (to Stash)

Shelve and restore incomplete changes (see also: Git Stashing)

$ git stash [<msg>]  # Temporarily stores all modified tracked files
$ git stash list     # Lists all stashed changesets
$ git stash pop      # Restores the most recently stashed files, removing top of stash
$ git stash apply    # Restores the most recently stashed files, without removing top of stash (no popping)
$ git stash drop     # Discards the most recently stashed changeset  
$ git stash clear    # Clear stash

Review History

Browse and inspect the evolution of project files

$ git log                   # Lists version history for the current branch
$ git log --follow [file]   # Lists version history for a file, including renames
$ git diff [first-branch]...[second-branch]  # Shows content differences between two branches
$ git show [commit]         # Outputs metadata and content changes of the specified commit  

Redo Commits

Erase mistakes and craf replacement history

$ git reset [commit]          # Undoes all commits afer [commit], preserving changes locally
$ git reset --hard [commit]   # Discards all history and changes back to the specified commit  

Synchronize Changes

Register a repository bookmark and exchange version history

$ git fetch [bookmark]           # Downloads all history from the repository bookmark
$ git merge [bookmark]/[branch]  # Combines bookmark’s branch into current local branch
$ git push [alias] [branch]      # Uploads all local branch commits to GitHub
$ git pull                       # Downloads bookmark history and incorporates changes  

Merge or Rebase

Merge the master to the feature branch:

$ git checkout feature
$ git merge master

Or, you can condense this to a one-liner:

$ git merge master feature

As an alternative to merging, you can rebase the feature branch onto master branch using the following commands:

$ git checkout feature
$ git rebase master  

The golden rule of git rebase is to never use it on public branches. For example, never rebase master onto the feature branch. This affects all developers, which causes a lot of problems.

If you treat rebasing as a way to clean up and work with commits before you push them, and if you only rebase commits that have never been available publicly, then you’ll be fine. If you rebase commits that have already been pushed publicly, and people may have based work on those commits, then you may be in for some frustrating trouble, and the scorn of your teammates.

FYI, you could run git pull –rebase to try to reduces issues after it happens.

At this point, you can go back to the master branch and do a fast-forward merge.

$ git checkout master
$ git merge feature

References:

Remote Git Server

To have Git working as a remote backup repository, create the remote repository as a bare repository (by convention, a bare repo has .git at the end):

$ mkdir my_remote_repo.git
$ cd my_remote_repo.git
$ git --bare init

Now clone that remote repository:

$ git clone [url-my_remote_repo]

Now, using the new working copy, you can add files then push those files back into the remote repo. The remote location will not have a working tree.

Alternatively, to turn an existing “non-bare” repository into a “bare” repository in Git, you can do this:

$ git clone --bare [non-bare-repo] [new-bare-repo]

You can also:

  • Create a bare remote repo.
  • Clone a local repo (populated with a working copy).
  • Point the new local copy to the remote repo, and push all the changes to the new remote repo.
  • The original local repo can now point to the remote repo (and optionally delete the local duplicate copy).
Remote Git Repositories
  • BitBucket - Free unlimited private repositories for 5 users
  • GitHub - Free unlimited public repositories for any number of users
Setup Local Repo to Push to BitBucket Repo using SourceTree

Install SourceTree and add BitBucket account:

  1. On the SourceTree application options (Tools > Options > Authentication > Accounts), add a BitBucket account.

Set the authentication to use Preferred Protocol SSH instead of HTTPS.

  1. On the SourceTree local repo, go to Settings and change remote origin address from https (ie: https://[username:password]@bitbucket.org/[username]/[repo].git) to ssh (ie: git@bitbucket.org:[user]/[repo].git). You will find these addresses at the top of your BitBucket repository page.

Create an SSH key

  1. On SourceTree, select Tools > Create or Import SSH Keys.
  2. In PuTTY Key Generator, generate a 2048-bit SSH-2 RSA key, then:
    • Copy the public key.
    • Save the private key locally.
    • Save the public key.

Install Private Key on Pageant (PuTTY Authentication Agent)

  1. Run Pageant or open from icon tray.
  2. Add private SSH key, by clicking on Add Key button, then entering the passphrase.

Add Public Key to BitBucket

  1. In SourceTree, open the PuTTY Key Generator from Tools > Create or Import SSH Keys.

Click Load and select the private key file.

  1. Copy the public key.
  2. On BitBucket Account Settings (user avatar), select SSH keys, then Add Key.
  3. Enter label “Default Public Key”.
  4. Paste public key to Key field, and save.

References

Git Flow

Organizing your repository to use git flow. Author: Vincent Driessen | Original blog post: http://nvie.com/posts/a-succesful-git-branching-model | License: Creative Commons BY-SA

References