Git has a steep learning curve but persistence pays off. Now that I’ve got the hang of it I can slosh code changes between multiple branches like a motherfucking wizard. Here is a cheatsheet I’ve developed for myself that has helped a lot. This isn’t a complete git HOWTO, it’s more of a list of things that I kept doing wrong as I was learning the system. The tips start relatively basic and get more and more complex. I was coming from svn and bzr so a lot of my tips have to do with confusion that results in coming from those systems.
Rule #1: When in doubt, checkout!
set username:
git config --global user.email user@domain
git config --global user.name 'Owen Williams'
set merge tool:
git config --global merge.tool meld
checking out:
git clone [url]
update changes from remote branch:
git pull
(does git fetch and then merges in the changes)
revert a file:
Don’t use “reset”!
git checkout [file]
show a single diff:
git show [sha]
create a branch:
(Don’t actually use this, because the next command is better)
git branch [newbranch]
create a branch and switch to it:
git checkout -b [newbranch]
(-b runs git branch first to create the branch. You could also git branch [newbranch]
and then git checkout [newbranch]
.)
This works even if you’ve started working! The changes will be moved over to the new branch 🙂
list branches:
git branch -a
switching branches:
git checkout [branch name]
merge all changes from another branch:
git merge [branch]
merge single commit from another branch:
(Only use this as a last resort, you lose wondering commit-tracking this way)
git cherry-pick [sha]
merge individual files from another branch:
git checkout source_branch [files]
fixing conflicts:
git mergetool
This uses the configured diff tool, or -t [toolname].
Note that with meld, the file called “BASE” (in the center) is the one that is used for the final commit. This is handy because you can pick which edits from the local you want, and which ones from the remote you want. Or just edit the <<< >>> file like you usually do. I find a good way to work is to blindly merge everything from the REMOTE to BASE first. Then I can see what’s different between the REMOTE and LOCAL which is usually what I want to do.
undo a merge in progress:
git merge --abort
reverting a commit:
You’re in trouble now, but this can be done. Examine git reflog
which lists all commits for all branches. You want to rewind to before the bad commit.
git reset HEAD@{2}
(or whatever label)
Default reset is –mixed, which seems to be ok. don’t do a –hard, like, ever.
When you do a reset, you’ll still be in a weird place with a lot of weird commits, but at least you saved your log. Examine the files and do a commit right away.
DO NOT DO git reset --soft [SHA]
from trunk if you’re in a branch! — this will BLOW AWAY your original log of changes, ie how you got to this point in your branch. You’ll have all those changes, but none of the intermediate work.
create a new branch from current that tracks a remote branch other than master:
need to create a local branch that tracks the remote branch
don’t include “remotes/”
git checkout --track -b mybranch origin/branch
tell git that the current branch should always inherit changes from another branch
git branch -u [parent branch]
git pull is familiar for pulling from a remote repo, but it also works between branches. This is great for hierarchical featuresets, ie:
feature1
feature1-feature2
So let’s say feature1 is in code review, I can keep that clean but keep working on the next feature. I can tell feature1 to pull from master, and feature1-feature2 to pull from feature1. (I name my branches like that so I don’t get lost in the tree.) After doing this to every branch, I can run git pull no matter where I am and everything will be in sync.
copy one repository to another:
Ok so this is trickier, but possible.
first, clone the new repo.
Add the other repo as a remote. here “other-repo” is the name of the new remote branch.
git remote add other-repo [other branch location]
git fetch other-repo
git checkout other-repo/master
Since you can’t actually check out a remote branch, you’re in limbo. Give it a name, creating a place where the other master branch will reside. This is where you’re doing the merge from the old into the new repo.
git checkout -b other_master
git merge master
resolve any conflicts between the two repos. Trust the LOCAL changes, not remote! you want the new master to be in charge, yes?
Now for every branch on the other repo you care about:
check it out
git checkout other-repo/branchname
copy that to local
git checkout -b branchname
merge in the changes that bring it in line with current master:
git merge other_master
then to check your work, compare against new master
git diff master
also notice that all your commits are preserved!
git log