git

One-time setup

Further info on the web

Popular git tools

- command line!

- GitX: http://gitx.frim.nl/

- Gitnub: http://github.com/Caged/gitnub/downloads

Setup config and aliases (some are optional)

required: tell Git who you are going to commit as.

If you skip the --global, these settings will only be for the current folder

git config --global user.name "Your Name Comes Here"

git config --global user.email you@yourdomain.example.com

Example for jmg who has an existing setup for github:

git config user.name "Jean-Michel Garnier"

git config user.email jmg@xxx

Check out your configuration with:

cat .git/config

Global .gitignore file

git config --global core.excludesfile ~/.gitignore

Next add the exclude line for .DS_Store to the .gitignore file either with your favourite editor or simply with this command which will create it if it doesn’t already exist as well.

echo .DS_Store >> ~/.gitignore

optional: colorized command-line output (useful for diff, status)

git config --global color.diff auto git config --global color.status auto git config --global color.branch auto

optional: add the following aliases to .git/config in the betterplace directory:

they let you write 'git ci' instead of 'git commit', etc.

[alias] ci = commit st = status co = checkout

optional: Showing your Git branch in your shell prompt

# http://aaroncrane.co.uk/2009/03/git_branch_prompt/ function find_git_branch { local dir=. head until [ "$dir" -ef / ]; do if [ -f "$dir/.git/HEAD" ]; then head=$(< "$dir/.git/HEAD") if \ refs/heads/* ; then git_branch=" ${head#*/*/}" elif $head != '' ; then git_branch=' (detached)' else git_branch=' (unknown)' fi return fi dir="../$dir" done git_branch='' } PROMPT_COMMAND="find_git_branch; $PROMPT_COMMAND" green=$'\e[1;32m' magenta=$'\e[1;35m' normal_colours=$'\e[m' PS1="\[$green\]\u@\h:\w\[$magenta\]\$git_branch\[$green\]\\$\[$normal_colours\] "

based on http://aaroncrane.co.uk/2009/03/git_branch_prompt/

optional: git commands auto completion

http://denis.tumblr.com/post/71390665/adding-bash-completion-for-git-on-mac-os-x-leopard

Change last commit message

git commit --amend -m "your new message"

developing a feature in a feature branch

The general idea is to make a branch for every new feature you develop. That has advantages like:

    1. you can commit to your local repo as often as you like.

    2. when you're done, you can do one "sqashed" commit. this applies all your changes in one commit, easy to review and undo.

    3. when you have to do another task (bugfix), you can easily create a new branch off master and fix the bug, leaving your feature work uninfluenced.

It's described here: http://blog.hasmanythrough.com/2008/12/18/agile-git-and-the-story-branch-pattern

Revert last commit

git reset --hard HEAD^

It removes the commit from your repository and from your working tree. It’s the equivalent of a delete button on your repository with no “undo.”

Work with remote branch

From http://www.gitready.com/beginner/2009/02/02/push-and-delete-branches.html : so let’s say you have checked out a new branch, committed some awesome changes, but now you need to share this branch though with another developer. You can push the branch up to a remote very simply:

git push origin newfeature

Other developers in the team won't know about new remote branch until they run:

git fetch

remote: Generating pack...

remote: 100% (77/77) done

Unpacking objects: 100% (77/77), done.

[new branch] removing_mozilla_days -> origin/removing_mozilla_days

git checkout -t origin/removing_mozilla_days

OU

git branch --track removing_mozilla_days origin/removing_mozilla_days

Branch removing_mozilla_days set up to track remote branch removing_mozilla_days from origin.

to see which (remote) branches exist:

git branch -av

After that, to push to this remote branch:

git push origin removing_mozilla_days

squashing commits with rebase

Working on removing features (mozilla, xmas, etc), we use a remote branch so 2 developers can pair:

A -- B -- C master / D -- E -- F -- G removing_mozilla (lots of small commits)

In order to be able to reproduce what exactly is contained in the feature 'mozilla', we want to merge it into master with one commit. (squash-merge)

We want:

A -- B -- C -- H (squash D, E, F and G) master / \ D -- E -- F -- G removing_mozilla

Make sure your branch has the lastest changes from master

Rebase against the upstream frequently to prevent your branch from diverging significantly:

git fetch origin master git rebase origin/master

NB: This is often done by checking master out and pulling, but this method requires extra steps:

git checkout master git pull git checkout 3275-add-commenting git rebase master

rebase with the interactive option to squash several (or all) of your commits into a single commit

git rebase -i master

    1. Rebase 60709da..30e0ccb onto 60709da

    2. Commands:

    3. p, pick = use commit

    4. e, edit = use commit, but stop for amending

    5. s, squash = use commit, but meld into previous commit #

    6. If you remove a line here THAT COMMIT WILL BE LOST.

    7. However, if you remove everything, the rebase will be aborted.

Basically this tells Git to combine all four commits into the the first commit in the list.

Combine commit messages

    1. This is a combination of 4 commits.

    2. The first commit's message is:

    3. Adding license

    4. This is the 2nd commit message:

    5. Moving license into its own file

Since we’re combining so many commits, Git allows you to modify the new commit’s message based on the rest of the commits involved in the process. Edit the message as you see fit, then save and quit. Once that’s done, your commits have been successfully squashed!

Merge with master branch

git checkout master git merge removing_mozilla rake tests:run_before_commit git push

Do not forget to clean up and remove the remote branch with

git push origin :removing_mozilla_days

More info, see http://www.gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html

git rerere

http://pivotallabs.com/users/khicks/blog/articles/2119-git-config-rerere-enabled-true

Revert a merge

We need to be able to reproduce what exactly is contained in the xmas calendar.

So please make sure to do this change in a branch, and merge it into master with one commit. (squash-merge).

Unfortunately, I have forgotten a few files and then Fabian and Jan pushed. This is the state of my git tree is:

A (JM) -- B merge result (JM 962cf1) -- C (fdi) -- D (fdi) -- E(js) master

First, I want to create a remote branch to not to loose my work:

A(JM)-- B merge result (JM) -- C (fdi) -- D (fdi) -- E(js) master / B remove_xmas branch

git branch remove_xmas_calendar 962cf1

And then I want to revert the merge so master is clean:

git revert -n 962cf1cf0e -m 1 git commit . -m "reverted merge of remove_xmas_calendar as I have forgotten the js and want to ask Fabian to review my changes. I have do$ git commit . -m "reverted merge of remove_xmas_calendar as I have forgotten the js and want to ask Fabian to review my changes." git push

Have a look to http://www.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.txt for more explanations

deleting old remote branches

1) remove tracking of remote branches that don't exist anymore

git remote prune origin

2) list all remote branches

git br -r

3) delete remote branches you don't need anymore

git push origin :search_indexer_refactorings

cherry-pick

hen, for each commit I want to cherry pick, I simply do:

$ git cherry-pick -x sha1_of_the_commit

Tricks

Gitx to display all commits for a given folder

gitx master -- features/

github open source projects guide

USE github-gem ???!!

$ git clone git@github.com:21croissants/caprese.git

Once the clone is complete your repo will have a remote named “origin” that points to your fork on github. Don’t let the name confuse you, this does not point to the original repo you forked from. To help you keep track of that repo we will add another remote named “upstream”:

$ cd github-services $ git remote add upstream git@github.com:timcharper/caprese.git $ git fetch upstream

Note that we used the public clone URL for upstream, so we can’t push changes directly to it. We probably don’t have permission to do that anyway, which is why we’re creating a fork in the first place. If the upstream repo is private, you must use its private URL.

Some time has passed, the upstream repo has changed and you want to update your fork before you submit a new patch. There are two ways to do this:

$ git fetch upstream $ git merge upstream/master

$ git pull upstream master

git pull is a more direct way, but the merge it performs can be confusing if the user doesn’t expect it and a merge conflict results. git fetch will also grab all branches, where git pull grabs only the one specified.

If you have local commits that are not in the upstream branch, a normal merge will occur. If your local commits are in the upstream branch, a fast-forward merge will be done, moving your local branch to the same commit as upstream/master. If both repos have edits to the same location in the same file, you may run into a merge conflict. Conflicts must be resolved by hand and a commit made to complete the merge.

Now that your local branch has been updated, commit your changes, push, and send a pull request.

You may wish to do the fetch and merge manually, instead of letting git-pull do it for you. This can help avoid headaches caused by mysterious merge conflicts.