git cherry-pick

Git commit’s id is a hash of its contents and its history, and becomes a unique id for a specific commit. Even if it contains the same change, as the parent would be different, it’ll have a different id.

“git cherry-pick” takes a commit from somewhere else, and “play it back” where you are right now. Git will build a new commit with a different hash, as the parents are different, though the contents are the same. One thing to note is that git hash is branch agnostic. in Git, an branch is simply “a lightweight movable pointer to one of these commits” (from git branching)

The other day, I rebuilt a release branch for release (of course!). I had to fix one issue, so committed the fix to the release branch. I made a few other changes and revoked the change, as they were not really necessary. Now I wanted to cheery-pick the commit for the fix.

I did git log.

C:\Users\andrew.chaa\Documents\Projects\PopOpen [release]> git log
commit 36bfde24c821f36f84c6ec88c796ae6edac17286
Author: andrewchaa <>
Date: Wed May 13 15:45:34 2015 +0100
the version is updated to 0.8.6

commit 8c803f203a03b9bd11faca7a754e0f1f4c8ab1b3
Author: andrewchaa <>
Date: Tue May 5 11:23:34 2015 +0100
Added Logging. No more fixed time looping. Use MainWindowTitle and check if the found window has the same fil

I know the commit hash, 8c803f203a03b9bd11faca7a754e0f1f4c8ab1b3.

git checkout master
git cherry-pick 8c803f203a03b9bd11faca7a754e0f1f4c8ab1b3

Then the change is on top of the last commit on the master branch. I can push the change to the server.

git cherry-pick

Posh Git shows the current branch and the state of files in powershell prompt

It’s a set of PowerShell scripts that gives Git integration in PowerShell prompt.

https://github.com/dahlbyk/posh-git

The first thing you notice once you install it, is that it can show the current branch and the state of files, additions, modifications, and deletions within.

Another nice feature is tab completion.

For example,

git ch<tab> --> git checkout

You can install it via PsGet

Install-Module posh-git
Posh Git shows the current branch and the state of files in powershell prompt

git tips

I have used git for a year now on my personal projects, but it’s still mysterious. I feel like I need a good gui like TortoiseHG. Probably Git Extension is the most mature project in guifying git.

Setting up your git environment

Set up can be a times-taking and boring job, but well, you can skip it. It’s something you need to to properly, to make the whole experience pleasant!

An augmented .gitignore

This will ignore rails document, vim, emacs swap files, and Mac OS X Finder’s DS_Store.

# Ignore bundler config
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3

# Ignore all logfiles and tempfiles.
/log/*.log
/tmp

# Ignore other unneeded files.
doc/
*.swp
*~
.project
.DS_Store
bundler_stubs/

Configure git to use BeyondCompare

diff

$ git config --global diff.tool bc3
$ git config --global difftool.bc3.path "C:\Program Files (x86)\Beyond Compare 3\bcomp.exe"

merge

$ git config --global merge.tool bc3
$ git config --global mergetool.bc3.path "C:\Program Files (x86)\Beyond Compare 3\bcomp.exe"

To launch a diff with BC3, use the command “git difftool” or “git difftool foofile.txt”

Line endings

If you use git on windows like me, it’s better to configure it to “commit as-is, checkout as-is”.

git config --global core.autocrlf false

Pull behaviour

By default Git will merge remote changes with your local changes when pulling. This can result in an ugly commit graph that makes it difficult to track changes. Rebasing on the other hand results in a single commit line graph. Rebasing long-lived branches is not recommended.

The guidance is that when pulling; when you’re only making changes on the master branch (or any long-lived remote branch) always use rebase. If you’re working on a long-lived branch merge should be used when pulling in changes from the original branch or merging back to that branch.

git pull --rebase

github

Generate a new ssh key on your machine. Go for default file name and type in your password.

$ ssh-keygen -t rsa -C "your_email@youremail.com"

Then copy the key from id_rsa.pub and register it on your github.com.

Create an app first on github. Push your changes to it.

$ git remote add origin git@github.com:/first_app.git
$ git push -u origin master

Sometimes, you make a mistake while creating a remote origin. Then

$ git remote rm origin

Rename remote

$ git remote -v
appharbor       https://andrewchaa@appharbor.com/londonubf.git (fetch)
appharbor       https://andrewchaa@appharbor.com/londonubf.git (push)
origin  git@github.com:andrewchaa/LondonUbf.git (fetch)
origin  git@github.com:andrewchaa/LondonUbf.git (push)

$ git remote rename appharbor apphb

$ git remote -v
apphb   https://andrewchaa@appharbor.com/londonubf.git (fetch)
apphb   https://andrewchaa@appharbor.com/londonubf.git (push)
origin  git@github.com:andrewchaa/LondonUbf.git (fetch)
origin  git@github.com:andrewchaa/LondonUbf.git (push)

staging files

$ git add . // This will stage all files
$ git add -u // This will stage delete files
you put the period at the end.

Discard unstaged files

from http://stackoverflow.com/a/52713/437961

$ git checkout path/to/file/to/revert // for a specific file
$ git checkout -- . //This will delete all unstaged files. Make sure you put the period at the end.

Branch, edit, and merge

To edit readme file, you can checkout in to a new branch. It’s kind of a good practice that you protect the main branch by branching your change out. You can delete the temp branch afterwards.

git checkout -b modify-README
git mv README.rdoc README.md
mate README.md

it commit -a -m 'improve the README file'
git branch -d modify-README

-a means commit all files that you changed.
if you use -D, instead of -d, it will delete the branch even though you haven’t merged in the changes.

Creating a branch

git branch NuGetUpdate
git checkout NuGetUpdate

or this is one liner.

git checkout -b NuGetUpdate

Creating a remote branch

The title is a bit misleading. You just create a local branch and push it remotely, then the remote branch is created.

push <remote-name> <branch-name> // syntax

git branch 1.0-dev
git checkout 1.0-dev
git push origin 1.0-dev

Caching your credential

If you have to type in your username and password to push your change to github, your fingres and wrists will suffer. You can cache your credential for a certain period.

I cached it for 5 hours. If you want an hour, use 3600.

git config --global credential.helper 'cache --timeout=18000'

ignore ssl certificate error

when you commit to your company githup repository that doesn’t have signed certificate, unfortunately, you get an error. You can get around it by turning off the warning.

git config – –global http.sslVerify false

Git commit against tag with no branch

I honestly panicked. I wasn’t aware that the working directory was attached to any branch. I added and committed my changes (which took an hour of toil). Then it wasn’t in any branch. I checked out to master. All the changes seemed to be lost!

The saviour was git reflog. You can find your commit SHA1, and checkout with it.

D:\dev\files>git reflog
WARNING: terminal is not fully functional
ce0320e HEAD@{0}: checkout: moving from tempbranch to NuGetUpdate
ce0320e HEAD@{1}: checkout: moving from NuGetUpdate to tempbranch
ce0320e HEAD@{2}: merge tempbranch: Fast-forward
1b355c7 HEAD@{3}: checkout: moving from tempbranch to NuGetUpdate
ce0320e HEAD@{10}: commit: updated references with the downgraded framework
...

Then you can check it out, create a new branch, and merge the branch to master or whatever, phew!

$ git checkout ce0320e
$ git checkout -b <new_branch_name>
$ git checkout master
$ git merge new branch
$ git branch -d newbranch
$ git push ...
git tips

Setting up ruby on rails on ubuntu

First of all, I am following on-line version of rails tutorial (http://ruby.railstutorial.org/ruby-on-rails-tutorial-book?version=3.2#top). Michael recommends sublime text 2 as editor. I use textmate on my mac, but I wouldn’t have the luxury of mac at work, so I am giving a try.

open a terminal here

Since I comes from windows background, I don’t like navigating in terminal. This util will install a menu on nautilus file browser

$ sudo apt-get install nautilus-open-terminal

sublime text

You can download sublime text 2. I did and it is now in download folder. Ah, I don’t know how to install application ubuntu. Do I have to run setup file like windows or drag and drop to application folder like mac? Sublime forum says I can create an “apps” folder in /home/{user}/ and put it there. Luckily, the text seems to be a stand-alone files, so I copied the directory to /home/andrew/apps/.

install Git

The free chapter of Pro Git is very helpful. I simply did

$ sudo apt-get install git-core

Install Ruby

I did $ruby -v, and it has ruby 1.9.1. It should be all right, but I want to use the latest available. Michael recommends installing ruby by using RVM, so I will go for it.

I will use “aptitude”, following the instruction. To find out if you have “aptitude”, you can do

$ sudo aptitude

If you get an error then, you need to install it by doing the below.

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install aptitude

Let’s install git core and curl

$ sudo aptitude install build-essential git-core curl

Then install RVM. This helps you manage multiple versions of ruby.

bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )

This is a kind of weird command to me, a ubuntu beginner, but it seems to work. Once RVM is installed, you need to load it to terminal. By adding the following command, you can make it be loaded automatically each time you start bash shell.

$ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"' >> ~/.bashrc

Check if it is successfully installed. You may have to close your current terminal session and open again to load RVM. type

$ rvm notes

You should see the note if it is installed.

Now install several helpful ruby packages.

$ sudo aptitude install build-essential openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev zlib libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison

Finally, you are ready to install ruby. So far, all packages were for ruby, not ruby.

$ rvm get head && rvm reload
$ rvm install 1.9.3

Install Rails

use gem to install rails. I had to use “sudo” due to permission issue on my ubuntu.

$ gem install rails -v 3.2.3
$ sudo apt-get install libxslt-dev libxml2-dev libsqlite3-dev

Check the version by doing $ rails -v.

After I install rails in this way, I get an error saying “invalid gemspec invalid date format” It seems Ubuntu prefers installing rails through apt-get install gem

$ apt-get install gem

Please let me know if anything does not work in this post.

Afterward …

Errors

It is quite frustrating that you go through quite a few errors. It makes me miss windows’ simple msi installer!

“Could not find railties” error. For some reason, railties are not installed.

$ sudo gem install railties

“Gem::RemoteFetcher::FetchError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://bb-m.rubygems.org/gems/rack-1.4.1.gem)
An error occured while installing rack (1.4.1), and Bundler cannot continue.
Make sure that `gem install rack -v ‘1.4.1’` succeeds before bundling.”

This one is self-explanatory, I think. Just install rack.

$ sudo gem install rack -v 1.4.1

ruby version problem.
I kept losing RVM whenever I start a new terminal session. Put this settings to your bash config

$ gedit .bashrc

Then put this at the end of the file.
[[ -s “$HOME/.rvm/scripts/rvm” ]] && . “$HOME/.rvm/scripts/rvm” # This loads RVM into a shell session.

Then RVM will be loaded automatically, and you will have the same version of ruby each time.

not function. ‘rvm use …’ will not work
If you run rvm use on ubuntu terminal, you get this message. It is because your bash shell is not login shell by default. Open the terminal settings and integrate rvm with gnome terminal.

Setting up ruby on rails on ubuntu

Git, Merging from Remote Branch

I did this on Bash on Windows 7 (64bit) against my github account.

I tried to push my change to github, and found it’s not possible.


$ git push -u origin master

Enter passphrase for key ….:
To git@github.com:andrewchaa/JonSkeetCSharp4Examples.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to ‘git@github.com:andrewchaa/JonSkeetCSharp4Examples.git
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. ‘git pull’) before pushing again. See the
‘Note about fast-forwards’ section of ‘git push –help’ for details.

So, I need to merge the change. I remembered I committed some code last night at home.


$ git fetch origin

Then


$ git checkout --track -b originmaster origin/master

Branch originmaster set up to track remote branch master from origin. Switched to a new branch ‘originmaster’

Now you check out your master branch (local)


$ git checkout master

Switched to branch ‘master’
Your branch and ‘origin/master’ have diverged,
and have 1 and 1 different commit(s) each, respectively.

And also checkout (get latest in TFS terms) originmaster


$ git checkout originmaster

Switched to branch ‘originmaster’

Now point to master back to start merge


$ git checkout master

Switched to branch ‘master’
Your branch and ‘origin/master’ have diverged,
and have 1 and 1 different commit(s) each, respectively.

In the mean time, I had to set up beyondcompare for git.


$ git config --global diff.tool bc3

$ git config --global difftool.bc3.path "C:/Program Files (x86)/Beyond Compare 3/bcomp.exe"

$ git config --global merge.tool bc3

$ git config --global mergetool.bc3.path "C:/Program Files (x86)/Beyond Compare 3/bcomp.exe"

You can see on which branch you are


$ git branch

* master

originmaster

Now, finally merge


$ git merge originmaster

Merge made by recursive.

Examples/ArrayExample.cs | 41 ++++++++++++++++++++++++++++++++++++++++
Examples/CollectionsExample.cs | 40 +++++++++++++++++++++++++++++++++++++++
Examples/Examples.csproj | 2 +
3 files changed, 83 insertions(+), 0 deletions(-)
create mode 100644 Examples/ArrayExample.cs
create mode 100644 Examples/CollectionsExample.cs

Then, it’s done.


$ git status

# On branch master
# Your branch is ahead of ‘origin/master’ by 2 commits.
#
nothing to commit (working directory clean)

Then, push back to githum


$ git push -u origin master

Enter passphrase for key ‘…..’:
Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 1.31 KiB, done.
Total 7 (delta 4), reused 0 (delta 0)
To git@github.com:andrewchaa/JonSkeetCSharp4Examples.git
cf1a6ea..59b280f master -> master
Branch master set up to track remote branch master from origin.

To summarise, I use the following commands


$ git fetch origin
$ git checkout --track -b originmaster origin/master
$ git checkout master
$ git checkout originmaster
$ git checkout master
$ git config --global diff.tool bc3
$ git config --global difftool.bc3.path "C:/Program Files (x86)/Beyond Compare 3/bcomp.exe"
$ git config --global merge.tool bc3
$ git config --global mergetool.bc3.path "C:/Program Files (x86)/Beyond Compare 3/bcomp.exe"
$ git branch
$ git merge originmaster
$ git status
$ git push -u origin master

Git, Merging from Remote Branch

Undo git add before the first commit

As git newbie, this was very tricky but it happens quite often.

You create a new project, say C# project. In case of rails, when you create a new project, it automatically creates .gitignore, but Visual Studio doesn’t. You do “git add . ” and suddenly you realise you staged so many unnecessary files like resharper cache, dlls, etc.

You don’t have any branch yet, as you din’t make the first commit. You can’t do “git reset .”

Anyway, to make a long story short, you have to

git rm -r --cached .

 

If you want to have more detailed version of a similar story, go to http://stackoverflow.com/a/682343/437961

Undo git add before the first commit