Skip to content

git tips

John Peterson edited this page Dec 5, 2013 · 5 revisions

git tips

Setup

  1. Install Git. On mac, git comes with Xcode's command line tools. If for some reason you don't have git and don't want to install Xcode, you can download it here: http://git-scm.com/download/mac On Windows, you can get it here: http://msysgit.github.io/

  2. Follow the setup steps here: https://help.github.com/articles/set-up-git At the very least, you'll want to do something like:

git config --global user.name "Your Name Here"
git config --global user.email "your_email@example.com"

And, you can make your life even better by also doing the following to make all your git commands print stuff in color:

git config --global color.ui true
  1. Finally, you'll probably want to do something about caching your password. For mac users, you can follow the stuff on the page above about enabling password caching. Alternatively (e.g. if you're using Windows or your version of git is too old), set up a .netrc (mac) or _netrc (windows): http://ithaca.arpinum.org/2010/10/14/fun-with-netrc.html

Doing work

  1. Clone a repo:
git clone https://github.com/adobe-photoshop/github-sandbox.git [dir to clone into]

With the public github, it's best to use the https url, so you don't have to get around the corporate firewall. With corporate github, you must use the ssh url.

  1. Do any feature development work in a branch:
# create a new branch that points to whatever your current branch head points to
git branch [branch name]
# actually switch to the new branch
git checkout [branch name]

or, do it all in one shortcut command

git checkout -b [new branch name]

It's customary to name your branch with your initials followed by a "/" and then a short description of the feature. So, something like "jrb/my-awesome-feature"

  1. Do some actual work (create and edit files)

  2. See what you changed with git status

  3. Stage files for committing with git add [filename]. Note that you "add" both files that are completely new (not yet in the repo) and that have changed. The add command gets them ready for a commit. After you stage them, when you do git status, you'll see them listed under "Changes to be committed"

  4. Actually commit your files with git commit -m 'some message'. If you don't use the -m option, git will open your $EDITOR and let you type a commit message.

  5. Right now, your hard work is only on your local repo. To show it to others, you need to put it up on some remote repo (like the one on github). You can see all your remote repos with git remote -v. If you cloned from github, you'll probably have one called "origin". To put your branch up on that repo, you "push" it:

git push [repo name] [local branch name]:[remote branch name]

So, you'll want something like:

git push origin jrb/my-awesome-feature:jrb/my-awesome-feature

If the local and remote branch names are the same (they usually are), you can just list the branch name once:

git push origin jrb/my-awesome-feature

If you want your local branch to "track" the remote branch (which means a git pull will automatically merge remote changes to your local branch, you can throw a "-u" option in there:

git push -u origin jrb/my-awesome-feature

Or, if you forget to do that, you can always do it later with

git branch --set-upstream [local branch name] [remote name]/[remote branch name]

So, something like:

git branch --set-upstream jrb/my-awesome-feature origin/jrb/my-awesome-feature
  1. Check out what branches you've got with git branch -avv. The "-a" shows remote branches, and the "-vv" gives you lots of output.

Getting someone else's work

  1. The easiest-to-understand way to get remote work is to do git fetch [remote name]. This will bring all of the remote branches from "remote name" into your local repo. So, if there was a branch named "jrb/foo" on origin and you do git fetch origin then you'll have a branch in your repo named "origin/jrb/foo"

  2. Once you've fetched, you can merge remote branches (that are cached in your local repo) into your local branches. So, if you have local branch "jrb/foo" you could do:

git checkout jrb/foo # if you're not already on that branch
git merge origin/jrb/foo
  1. Doing git pull will do all kinds of magical stuff. It'll start by doing a git fetch behind the scenes. Then, for any local branch that is tracking a remote branch (see above), it will attempt to automatically merge the remote branch into the local branch. If you don't want to pull all branches, you can do git pull [remote name] [local branch name]. This will only work if "local branch name" is tracking some remote branch on "remote name". A common command is git pull origin master, because local master is usually tracking a remote master on a remote called "origin"

Getting work into master

If you're like me, you'll probably make a mess in your branch with all kinds of interim commits. It's nice to clean those up before they end up in master. In an ideal world, every commit in master would be a "working" version. That way, the "bisect" command can be used to find when bugs are introduced, etc.

Often, before putting up a "pull request" (which is a github, but not git, concept), it's useful to both rebase and squash/rewrite your commits. It sounds like a lot of work, but it's actually really easy.

  1. Make sure you have the latest remote master with ```git fetch````

  2. Make and checkout a new branch that points to the same place your current branch head does (assumes you already have the current branch you want to be in master already checked out):

git checkout -b jrb/my-ready-to-merge-feature
  1. "Rebase" all your commits to origin/master. Rebasing to a point "foo" means "find the first commit in your branch that diverges from the master branch, then move all commits in your branch to occur after 'foo'". In other words, it moves the base of your branch to the new location.
git rebase -i origin/master

The "i" option will cause an interactive rebase. Your $EDITOR will launch.

  1. In this interface, you can choose to keep, squash, fixup (keep but change commit message), or throw out any commits. Note that this will only affect your NEW branch. Your old branch will stay exactly as it was in case you screw up. Once you save that file, you'll then get new editor windows to fix up anything you specified.

  2. Push this new branch to the github. Go to github and create a pull request. Get someone to review it.

What's a pull request?

"Pull Requests" are a github (but not git) concept. The only way you can make one is by logging in to github.com and using the web UI. Basically, it's a way to say to other people working on your repo "hey, I'd like to merge branch 'a' into branch 'b'". 99% of the time, branch "b" will be master.

Github has a nice interface where you can discuss pull requests, do code reviews, and so forth. You can go look at some closed ones in this repo.

Pull requests have a "merge" button that will basically run git fetch; git checkout b; git merge a; git push origin b. In other words, it'll actually do the merge on the remote repo.

If there's an open pull request and some developer fires up a command line and just does the merge (and then pushes the merge to github) it will automatically close the pull request (since the merge actually happened). More generally, if the "source" branch of the pull request ends up as part of the "destination" branch by any action, the pull request will be closed.

What's a fork?

Git is a distributed version control system. Really generally speaking, every single clone of a repo is a fork.

Github has a formalized concept of "forks". Basically, it's a way for developers to easily contribute to repos they don't have write access to. A github user can "fork" any repo that they have read access to. This gives them a write access version in their own namespace. They can then make edits, and put up a pull request (using github.com) from their fork to the main repo.

Since we all have r/w access to the main repo, we don't NEED to use forks. But, if you want to, you can. On Brackets, for instance, I use my own fork to do really experimental stuff that I wouldn't want to check in to the main repo. If I end up wanting to submit some of it, I can still put up a pull request.

Resolving Merge / Rebase conflicts

This basically works like every other version control system. If you have a merge tool set up (google on how to do this), the merge tool will launch when you do a git merge or git rebase with a conflict. If you're a command line dood, you'll just get an error and git will put some ">>>>>>" strings in the conflicted file. Fire up an editor, fix the file(s), do a git add followed by git commit and you're all set. (With a rebase, you might have to do git rebase --continue.) You can bail on a merge/rebase with git merge --abort or git rebase --abort.

The ps-next branch

For those that care (probably only me), here's the workflow for creating a pull request into ps-next:

  1. Check out the ps-next branch, and make sure you're fully in sync with the remote ps-next branch. (with something like git checkout ps-next; git pull origin ps-next)

  2. Create a branch off of the ps-next branch (with something like git checkout -b my-feature-name)

  3. Cherry-pick the commit(s) you want onto your new branch (with something like git cherry-pick [some SHA]) or change the code however you want and make a new commit

  4. Push your feature branch to the server (with something like git push origin my-feature-name) Go to github.com and create a pull request with "ps-next" as the base branch rather than "master" as the base branch

  5. Find some sucker to code review it

For all other feature work, just do it like we've always been: make a feature branch, do the development, merge it into master yourself if it's simple, or get a code review to merge in to master if it's complicated.

GUI tools

Someone else will have to comment on this. Some people like "Tower" and "SourceTree" on the mac. I have no idea what people use on Windows.

Make your mac command line awesome

The command line in git-bash on Windows is already awesome (it shows current branch and has great autocomplete).

To get something similar on mac, you need to edit your .bash_profile and source a few scripts that ship with Xcode/git. My bash profile looks like this:

source /Applications/Xcode.app/Contents/Developer/usr/share/git-core/git-completion.bash
source /Applications/Xcode.app/Contents/Developer/usr/share/git-core/git-prompt.sh
PS1='\[\e[0;30m\][\u@\h:\W$(__git_ps1 " (%s)")]\$\[\e[0m\] '

if [ -f `brew --prefix`/etc/bash_completion ]; then
  . `brew --prefix`/etc/bash_completion
fi

Also, installing bash-completion will make your life way more amazing (even when not using git):

  1. First, install homebrew if you haven't: http://mxcl.github.io/homebrew/ (Sure, it's crazy to curl a random file on the Internet, pipe it directly in to ruby, and then type in your root password when prompted. But it's Adobe's computer, not yours...)

  2. Do brew install bash-completion