Random Tech Thoughts

The title above is not random

Git

Basic configuration

User information

Tell git your name and email address that would appear in the git commit message

$ git config --global user.name "Chen Yufei"
$ git config --global user.email [email protected]

git config --global will add configuration in $HOME/.gitconfig. Manually editing that file has the same effect.

Useful alias

Using aliases, I can for example just type git st instead the lengthy git status. I have the following aliases:

[alias]
    st = status
    ci = commit
    co = checkout
    br = branch
    rb = rebase

Formatting and Whitespace

From Pro Git chapter 7-1

Handling carrage return (CR)

Rules:

  • Code in git repository should not have carrage return. (Unless this is a windows-only project.)
  • For windows user, execute git config --global core.autocrlf auto. This option will:
    • When check out code, convert LF (line feed) to CRLF
    • When commit code, convert CRLF to LF
  • For Unix users, execute `git config --global core.autocrlf input. This will
    • When commit code, convert CRLF to LF. This can remove CRs for code in the repository

Interacting with Subversion repository

I never felt want to use svn anymore after using git. And we are lucky to have git-svn to interact with svn using git.

  • Clone

    git svn clone -s -r 40000:HEAD <url>
    
    • -s is for --stdlayout
    • -r is for the revision to start taking history from

git bisect

git bisect is a really useful command to locate a regression bug. Search the commit that introduced the bug using binary search. How to use:

  1. Starting a bisect git bisect start
  2. Mark one revision as good, and another as bad, and git will find a commit for us to test

     git bisect bad # mark the current commit as bad
     git bisect good v1 # marks the specific tag, or commit as good
    
  3. Keep testing and use git bisect <good | bad> to mark if this is a good commit. Finally, git will stop at the commit which introduced the bug.

Fetch and pull with refspec

Git pull/fetch with refspec differences

  • Remeber pull is fetch followed by merge FETCH_HEAD
  • refspec is for fetch

Notes for Reset Demystified

How git reset works:

  • First change what HEAD points to. (HEAD is like pointers in C, git reset is like assignment using dereferencing.)
    • Compare this to git checkout, it changes which branch HEAD points to
  • With --soft option (default), reset stops here
  • With --mixed, reset will also change the index to reflect HEAD
  • With --hard, reset will change your working file to reflect HEAD

reset with a path

  • Will not change what HEAD points to
  • With --mixed (default), make content in index looks like what’s in HEAD. This equivalents to unstage the file
    • If given a commit id, put the content given in the commit id into the index

Versus checkout

  • checkout is working directory safe. It will update all of the working directory except the files you’ve modified if it can
  • checkout will move HEAD to point to another branch

  • git checkout [branch|commit] file is equivalent to git reset --hard [branch] file

    • Actually reset can’t be invoked with a file name and --hard
    • This checkout is not working directory safe
    • Will not modify HEAD

Changing remote repository

If we want to change the origin repository to something else:

git remote rename origin foo
git remote rename bar origin

This will correctly change the remote used to pull for the relating branch.

To change which remote to use for a branch (use master for example)

git config branch.master.remote foo

Manually editing .git/config also works.

Notes for A successful Git branching model

Recomend use git flow

I hope I read it when I started to use branch.

2 main branches:

  • master branch. Reflect a production-ready state
  • develop or integration branch. Reflect latest delivered development changes for the next release. Nightly builds built from here.

Supporting branches

  • Feature branch

    • Naming convention: anything except master, develop, release-*, or hotfix-*
    • May branch off from develop

      $ git checkout -b myfeature develop
      
    • Must merge back into develop

      $ git checkout develop
      $ git merge --no-ff myfeature
      $ git branch -d myfeature
      $ git push origin develop
      

      Note --no-ff always create a commit object even can be fast-forward.

    • When starting development of a feature, the target release in which this feature will be incorporated may well be unknown at that point.

    • Maybe discarded
    • Exists in developer repos only, not in origin
  • Release branch

    • Naming convention: release-*
    • May branch off from develop

      $ git checkout -b release-1.2 develop
      $ ./bump-version.sh 1.2
      $ git commit -a -m "Bumped version number to 1.2"
      
    • Must merge back into master

      $ git checkout master
      $ git merge --no-ff release-1.2
      $ git tag -a 1.2
      
      $ git checkout develop
      $ git merge --no-ff release-1.2
      
      $ git branch -d release-1.2
      
    • Allow for minor bug fixes and preparing meta-data for a release

    • All features that are targeted for the release-to-be-built must be merged in to develop at this point in time
    • Bug fixes may be applied in this branch (rather than on the develop branch) before release branch is merged into master
  • Hotfix branch

    • Branch naming convention: hotfix-*
    • May branch off from: master

      $ git checkout -b hotfix-1.2.1 master
      $ ./bump-version.sh 1.2.1
      $ git commit -a -m "Bumped version number to 1.2.1"
      
      $ git commit -m "Fixed severe production problem"
      
    • Must merge back into: develop and master

        $ git checkout master
      $ git merge --no-ff hotfix-1.2.1
      $ git tag -a 1.2.1
      
      $ git checkout develop
      $ git merge --no-ff hotfix-1.2.1
      
      $ git branch -d hotfix-1.2.1
      
    • Like release branches, also meant to prepare for a new production release, but unplanned

    • When a release branch currently exists, the hotfix changes need to be merged into that release branch, instead of develop

Git rerere

From Rerere Your Boat. “rerere” stands for “reuse recorded resolution”. Useful for rebase.

To enable it

git config --global rerere.enabled 1

Set default branch in a bare repository:

  git symbolic-ref HEAD refs/heads/<default branch>

Retrieve a single file from a specific version

From StackOverflow

Syntax

git show object
git show $REV:$FILE
git show HEAD^^^:test/test.py

The command takes the usual style of revision, meaning you can use any of the following:

  1. HEAD + x number of ^ characters
  2. The SHA1 hash of a given revision
  3. The first few (maybe 5) characters of a given SHA1 hash

Choosing ours/theirs file upon conflict

This is especially useful for resolving binary file conflicts.

From StackOverflow

If you have a merge conflict, and you know you just want the file from the branch you are merging in, you can do:

$ git checkout --theirs -- path/to/conflicted-file.txt

to use that version of the file. Likewise, if you know you want your version (not the one being merged in) you can use

$ git checkout --ours -- path/to/conflicted-file.txt

Reduce git repository size

From StackOverflow.

git remote prune origin
git gc --aggressive --prune=now