Git is a fast, flexible but challenging distributed version control system. Before jumping in:
Along with a book, tutorial and cheatsheet, here are the insights that helped git click.
There's a staging area!
Git has a staging area. Git has a staging area!!!
Yowza, did this ever confuse me. There's both a repo ("object database") and a staging area (called "index"). Checkins have two steps:
git add foo.txt
- Add foo.txt to the index. It's not checked in yet!
git commit -m "message"
- Put staged files in the repo; they're now tracked
- You can "
git add --update"
to stage all tracked, modified files
Why stage? Git's flexible: if a, b and c are changed, you can commit them separately or together.
But now there's two undos:
git checkout foo.txt
- Undo local changes (like svn revert)
git reset HEAD foo.txt
- Remove from staging area (local copy still modified).
Add and commit, add and commit -- Git has a rhythm.
Branching is "Save as..."
Branches are like "Save as..." on a directory. Best of all:
- Easily merge changes with the original (changes tracked and never applied twice)
- No wasted space (common files only stored once)
Why branch? Consider the utility of "Save as..." for regular files: you tinker with multiple possibilities while keeping the original safe. Git enables this for directories, with the power to merge. (In practice, svn is like a single shared drive, where you can only revert to one backup).
Imagine virtual directories
I see branches as "virtual directories" in the .git folder. While inside a physical directory (c:\project or ~/project), you traverse virtual directories with a checkout.
git checkout master
- switch to master branch ("cd master")
git branch dev
- create new branch from existing ("cp * dev")
- you still need to "cd" with "git checkout dev"
git merge dev
- (when in master) pull in changes from dev ("cp dev/* .")
git branch
- list all branches ("ls")
My inner dialogue is "change to dev directory (checkout)... make changes... save changes (add/commit)... change to master directory... copy in changes from dev (merge)".
The physical directory is a scratchpad. Virtual directories are affected by git commands:
rm foo.txt
- Remove foo.txt from your sandbox (restored if you checkout the branch again)
git rm foo.txt
- Remove foo.txt from current virtual directory
- Gotcha: you need to commit that change!
Know the current branch
Just like seeing your current directory, put the current branch in your prompt!
In my .bash_profile:
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* (.*)/(1)/'
}
export PS1="[33[00m][email protected][33[01;34m] W [33[31m]$(parse_git_branch) [33[00m]$[33[00m] "
Visualize your branch structure
Git leaves branch organization to you. Nvie.com has a great branch strategy:
- Have a mainline (master). Mentally it's on the far right.
- Create branches (master -> dev) and subbranches (dev -> featureX). The further from master, the crazier.
- Only merge with neighbors (master -> dev -> feature X, or featureX -> dev -> master)
Stay sane by choosing a branch layout up front. I have a master tracking a svn project, and dev for my own code. In general, master is clean so I can branch anytime for one-off fixes.
Understand local vs. remote
Git has local and remote commands; seeing both confused me ("When do you checkout vs. pull?"). Work locally, syncing remotely as needed.
Local data
git init
- create local repo
- use git add/commit/branch to work locally
Remote data
git remote add name path-to-repo
- track a remote repo (usually "origin") from an existing repo
- remote branches are "origin/master", "origin/dev" etc.
git branch -a
- list all branches (remote and local)
git clone path-to-repo
- create a new local git repo copied from a remote one
- local master tracks remote master
git pull
- merge changes from tracked remote branch (if in dev, pull from origin/dev)
git push
- send changes to tracked remote branch (if in dev, push to origin/dev)
Why local and remote? Subversion has central checkins, so you avoid committing unfinished work. With git, local commits are frequent and you only push when ready.
GUIDs are GOOD
Git addresses information by a hash (GUID) of its contents. If two branches are the same, they have the same GUID (and vice versa).
Why's this cool? We can create branches independently, merge them, and have a common GUID. No central numbering needed. Usually, we just compare the first few digits: "Are you on a93?".
Tips & Tricks
For your .gitconfig:
[alias]
ci = commit
st = status
co = checkout
oneline = log --pretty=oneline
br = branch
la = log --pretty="format:%ad %h (%an): %s" --date=short
There are some GUI tools for git, but I prefer to learn via the command line. Git is opinionated software (which I like), and analogies help me understand its world view.
Pingback: Aha! Moments When Learning Git | BetterExplained « Netcrema – creme de la social news via digg + delicious + stumpleupon + reddit()
Pingback: uberVU - social comments()
Pingback: Aha! Moments When Learning Git | BetterExplained : Popular Links : eConsultant()
Pingback: links for 2010-03-10 « BarelyBlogging()
Pingback: terra's me2DAY()
Pingback: links for 2010-03-10 « riverrun meaghn beta()
Pingback: How to Install and Get Up and Running Quickly with GIT – a Fast, Distributed Version Control System. « the seeker’s quill()
Pingback: Random Links #150 | YASDW - yet another software developer weblog()
Pingback: links for 2010-03-11 « Donghai Ma()
Pingback: Aha! Moments When Learning Git [ BetterExplained ]()
Pingback: Destillat #12 | duetsch.info - Open Source, Wet-, Web-, Software()
Pingback: git top links: 2010-2 « git blog()
Pingback: links for 2010-03-13 « B-link List()
Pingback: Links and Bits for March 15th — Alex Jones()
Pingback: 025.431: The Dewey blog: Earthquake Engineering | Structural Engineering Addict()
Pingback: Advanced research paper editing with Subversion revision control : Granthinām()
Pingback: Special Blog: Using Git and Other Useful Tips « Cassie's CS 371p Blog()
Pingback: Moving projects to GitHub « The Ubuntu Incident()
Pingback: Top 10 Git Tutorials for Beginners()
Pingback: Top 10 Git Tutorials for Beginners | SearchPsd Blog()
Pingback: Top 10 Git Tutorials for Beginners | Programming Blog()
Pingback: Design Magazine » Top 10 Git Tutorials for Beginners()
Pingback: ThemeDigg » Top 10 Git Tutorials for Beginners » ThemeDigg()
Pingback: Top 10 Git Tutorials for Beginners | WebFree.ro()
Pingback: Top 10 Git Tutorials for Beginners | JustMyLog.info()
Pingback: Top 10 Git Tutorials for Beginners | Designer Brisbane blog()
Pingback: Christians digest for June 13th | Christians lifestream()
Pingback: StartupDigest Hacker – June 17, 2011()
Pingback: Git is a powerful versioning system, here are some great tips | Josh Kerr()
Pingback: 10篇写给Git初学者的最佳教程 | Make The Change()
Pingback: Git branching best practices | Christoph Becker()
Pingback: (via Instapaper) | infiniteregress.org()
Pingback: Git学习的最佳教程 | 侯三儿()
Pingback: Zeh Fernando » Blog Archive » How I learned to stop worrying and love Git()
Pingback: Git学习的最佳教程 | EvilCode 邪恶代码()
Pingback: The Windows Companion to James Shore’s Let’s Code Javascript | Andrew Selbie Interactive()
Pingback: Yet another newb guide to git | Kaush's Journal()
Pingback: Why I’m starting to like git. | ChinPen()
Pingback: The R-Podcast Episode 12: Using Version Control with R » The R-Podcast()
Pingback: 7 Useful Git Tips for Beginners()
Pingback: 7 Useful Git Tips for Beginners | InfoLogs()
Pingback: Git Bash & Console2, Finally! | John Gilliland()
Pingback: 十个最好的Git学习教程 – 软飞()
Pingback: Git Bash and Console2 Finally Working! | Elusive Coding()
Pingback: 写给 Git 初学者的 7 个建议 | BugShow()
Pingback: 10篇写给Git初学者的最佳教程 | 新世纪Linux社区()
Pingback: Junwei Zhao » Post:()
Pingback: Git – Best Practices in Version Management | Champlin Technologies LLC()
Pingback: Git入门教程 PDF电子书+网站 | X的博客()
Pingback: 7 Useful Git Tips for Beginners - vcdblog()
Pingback: Top 10 Git Tutorials for Beginners | yitdeveloper's Blog()
Pingback: 写给 Git 初学者的 7 个建议()
Pingback: 7 Useful Git Tips for Beginners | Dan Gorman's Technology News Aggregation()