Wednesday, April 24, 2013

The Dilettante's Git Cookbook

I use Subversion at work, so I don't use git regularly enough to remember these little things.

Undo and Redo a Commit

First, understand how the git index works. Here's a good intro from the GitGuys.

Now, to undo a commit and redo it (from StackOverflow).
$ git commit ...              (1)
$ git reset --soft HEAD^      (2)
$ edit                        (3)
$ git add ....                (4)
$ git commit -c ORIG_HEAD     (5)
  1. This is what you want to undo
  2. This is most often done when you remembered what you just committed is incomplete, or you misspelled your commit message, or both. Leaves working tree as it was before "reset".
  3. Make corrections to working tree files.
  4. Stage changes for commit.
  5. "reset" copies the old head to .git/ORIG_HEAD; redo the commit by starting with its log message. If you do not need to edit the message further, you can give -C option instead.

Throw Away/Stash All Changes

This is something you might want to do when you’ve pushed changes to your upstream repo that are better than what you have in a (different) downstream.  In other words, you started something in a repo A, finished it in B, pushed from B, and now you don’t care about unfinished changes in A.

You can use git checkout . to forget all changes for tracked files, but it won’t get rid of any untracked files that you don’t want.  Be careful!  It doesn’t ask before blowing away all unstaged changes.

A better approach might be to just stash the changes.

git stash save --keep-index

You can use the stash list and stash apply commands to see your stashes and bring them back. Or they can be removed permanently with git stash drop.

Interactive Staging

It's time to end my practice of committing gobs of unrelated changes just because I'm too lazy to pick them out and separate them.  I didn't realize it was so easy.

git add -p

It's that simple.  You can choose which changes (called hunks in the context of patching) that you want to stage for the next commit.

This is useful if you started working on a new change but forgot to commit the previous work. 

Get the full story on interactive staging from Scott Chacon's free Pro Git book.

Repo Visualization with GitWeb

Although I have a github account, there are other work-related projects that require the use of an internal git repo.  I bounce around between different machines at the office, so it's nice to have a master repo that I can get to from anywhere.

I found GitWeb to be very easy to set up.  I already had Apache httpd running on my workstation, so a simple yum install gitweb added the necessities.

To my surprise (well, not too surprised given the way my brain works), I found that the git project directory /var/lib/git already had stuff in it... from a year ago! The rpm -qf /var/lib/git command showed that the directory was owned by the git-daemon package. The daemon wasn't running and my current research gave me reasons not to run it, so I removed the package.

Anyway, I didn't have to do much other than to restart the httpd service.  Once I did, I could browse to http://myworkstation/git and there were my projects. Cool!

Note that GitWeb only provides the ability to visualize your repositories in a browser.  It's not a vehicle for git operations like cloning and pushing.  See the next section for more info on that.

Remote Repo Access With SSH

For small groups of Linux users, SSH access to git is an easy way to go.  
  • Created bare repositories for each project 
  • Copy the bare repo's to /var/lib/git on the server
  • Create a git user account on the server
  • chown -R git:git /var/lib/git
  • Add the user public keys to ~git/.ssh/authorized_keys
Once you've done that, all users are free to clone from and push to any project using the git account.  Their commit messages will have the correct user info since that information is based on git configuration and not SSH login name.

For larger groups and project-specific access, Gitosis is the next step.

If you just want to clone a repo from one machine to another (which I like to do just for backing up trivial repositories), just use git clone node:path/to/repo.

No comments:

Post a Comment