Pragmatism in the real world

Some notes on git

This set of notes covers the main things that I think you need to know about working with git. It is not comprehensive and mainly serves as a reminder for myself.

Remotes

In a typical open source workflow using GitHub or BitBucket, you would fork the main repository into your own and then clone that copy to your local computer:

    git clone git@github.com:akrabat/joind.in.git

You then need to connect your local repository to the main repository. By convention, the main repository is known as upstream:

    cd joind.in
    git remote add upstream git://github.com/joindin/joind.in.git

To sync your local repository with upstream and update your copy back on BitBucket/GitHub:

    git checkout master
    git fetch upstream
    git merge --ff-only upstream/master
    git push origin

If the merge fails, then something bad has happened and you’ll need Google! One option is to force your master to match upstream using git reset --hard upstream/master and then git push --force origin.

Branching

The main branch in the repository is called master. Never ever code directly on master. Always create a branch and code on that and then merge back to master when complete.

(Note that the push command is also used throughout this document to sync your local repository with your remote on BitBucket/GitHub. If don’t want to publish, then don’t push.)

Create a branch:

    git checkout -b my-branch-name
    git push origin my-branch-name

List all branches:

    git branch -v

To list all remote branches too use the -a switch:

    git branch -v -a

Change from one branch to another:

    git checkout another-branch-name

Delete a branch:

    git branch -D my-branch-name
    git push origin :my-branch-name

Rebase master onto a branch:

If lots of people are working on the project, then master has probably changed a lot since you started. It’s going to make your merge back to master much easier if you update your branch so that all your changes appear to be after all the changes on master. This is known as rebasing:

    git fetch upstream
    git checkout my-branch-name
    git rebase -f upstream/master
    git push -f origin my-branch

Bring in a remote branch to your local repository:

If you want to work with a branch that’s on a remote repository, then you need to create your own tracking branch:

    git fetch upstream
    git checkout master
    git branch -t upstream/remote-branch-name
    git push origin remote-branch-name

The name of your local branch will match the remote branch name.

Sync remote branch with local one

    git fetch upstream
    git checkout remote-branch-name
    git merge upstream/remote-branch-name
    git push origin

Committing

To commit a change:

To commit a change, you first need to stage the files that you want to commit to the index:

    git add filename

You can then commit:

    git commit -m "my commit message"
    git push origin

Note that if you change a filename after adding to the index, then the change will not be committed unless your git add the file again. For information about a good commit message, read A Note About Git Commit Messages by Tim Pope.

Merging

Merge a branch into master:

    git checkout master
    git fetch upstream && git merge --ff-only upstream/master
    git merge --no-ff my-branch-name

Note that you don’t need to commit anything. You do need push though:

    git push

If there were conflicts, then you need to resolve them by editing the files appropriately (look for <<<<<<<). At this point, you do need commit your changes:

    git add .
    git commit
    git push

Back out a conflicted merge:

    git reset --hard HEAD

Working with your repository

To find out what’s happened:

    git reflog -10

This provides a list of the last 10 things that you’ve done on this repository across all branches.

    git log --oneline -10

This provides a list of the last 10 commits that’s happened on this branch

In both cases, the first column contains the commit hash reference that uniquely identifies each commit.

To find out current commit:

    git log -1

To undo all working changes

    git checkout .

To revert a commit:

Find the commit that you want to go back to via log or reflog:

    git reset --hard abcdef0

You can also use the ‘HEAD’ number from reflog:

    git reset --hard HEAD@{1}

To amend last commit message:

    git commit --amend -m "New commit message"

It’s best to do this before pushing. If you have pushed, then you need to force push using git push --force and expect to get lots of hassle from your co-workers.

Differences

To find out the differences between your edits and the last commit:

All files:

    git diff

One file:

    git diff -- my-filename

To find out the differences between current branch and master:

    git diff master..HEAD my-filename

To find out the differences between local master and origin’s master:

    git diff HEAD...origin/master

Some git aliases

Aliases provide a way to create new git commands and are usually used for creating shortcuts:

Type these from the command line:

    $ git config --global alias.st status
    $ git config --global alias.staged 'diff --staged'
    $ git config --global alias.unstage 'reset HEAD --'
    $ git config --global alias.last 'log -1 HEAD'

This gives you some new git commands:

  • git st => view current status
  • git staged => view the diff of what is currently staged
  • git unstage filename => Remove filename from the staging area
  • git last => view last commit

4 thoughts on “Some notes on git

  1. Just curious, but why not use

    git diff master…origin/master

    to get diff between master and origin? Your command may show differences between whatever branch you have checked out and origin, right? I also suggest having an alias for syncing your master, origin/master and upstream/master in one command.

  2. Better add –replace-all option to avoid recursion when run a second time.

    Try with: git config –global alias.staged 'diff –staged'

    Also, Windows requires double quotes for multi-word parameters.

    Examples:

    git config –global –replace-all alias.st status
    git config –global –replace-all alias.bra branch
    git config –global –replace-all alias.com commit
    git config –global –replace-all alias.staged "diff –staged"
    git config –global –replace-all alias.unstage "reset HEAD –"
    git config –global –replace-all alias.last "log -1 HEAD"

Comments are closed.