Remove old branches
Over time the amount of feature branches on my gh fork of my companies repository got out of hand (60+ branches). I wanted to remove the ones I'm not using. So I put togeather the following script

seen from United Kingdom

seen from United States
seen from Switzerland
seen from China
seen from United States
seen from Paraguay
seen from United Kingdom
seen from Oman
seen from United States

seen from United Kingdom
seen from United States

seen from United Kingdom

seen from United Kingdom
seen from Taiwan

seen from United Kingdom

seen from United Kingdom

seen from Singapore
seen from United States

seen from United States

seen from Russia
Remove old branches
Over time the amount of feature branches on my gh fork of my companies repository got out of hand (60+ branches). I wanted to remove the ones I'm not using. So I put togeather the following script

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Checkout out a remote branch in git
First you need to update the branches or your remote branch by doing
Get all branches on the remote server
git remote update origin
where origin is the name of your remote
Checkout and switch to new branch
git checkout -t origin/new-branch
Due to big space in our account at beanstalk, we decided to have all projects under the same company to be created under one repo. I know this is not a good practice, but for a small company with tight budget, this is they way to go.
So, since git has set the default branch as master, we need to clone a specific branch under that repo. Now I'm working on new project called DBMS2, the following is how you can retrieve the DBMS2 branch.
mkdir dbms2; cd dbms2
git init
git remote add -t dbms2 origin [my.git.url]
git fetch
git checkout dbms2
Thus when I do git branch, it will list dbms2 branch only. Kewl!
Remote Branch
Does your pair programmer maintain order, keeping the mean streets (ie. remote branches) clean? Let's ride along with a remote branch cop to see how they work.
fetch
Once inside the squad car, the cop runs git fetch origin:
remote: Counting objects: 45, done. remote: Compressing objects: 100% (27/27), done. remote: Total 28 (delta 23), reused 0 (delta 0) Unpacking objects: 100% (28/28), done. 0417137..5eb7f00 2933-upgrade-factory-girl -> origin/2933-upgrade-factory-girl * [new branch] 3159-fix-mobile-web -> origin/3159-fix-mobile-web
The manual tells us what happened:
> The above command copies all branches from the remote refs/heads/ namespace and stores them to the local refs/remotes/origin/ namespace.
This is useful for seeing what's new in the remote named origin.
rebase
If we're currently working in a local feature branch, we might look for something like this in the output of git fetch origin:
84d3635..19780cc master -> origin/master
If a line like that is in the output, there's something new in origin/master that we might want to investigate and git rebase origin/master into our feature branch.
tracking
However, the output in this case tells us that two remote branches have changed:
0417137..5eb7f00 2933-upgrade-factory-girl -> origin/2933-upgrade-factory-girl * [new branch] 3159-fix-mobile-web -> origin/3159-fix-mobile-web
The 2933-upgrade-factory-girl branch is one we had tracked and was since updated. The 3159-mobile-web-fixes branch is a new branch.
git branch -r
We view our existing known remote branches with git branch -r:
origin/2933-upgrade-factory-girl origin/3114-add-validations-for-subscription-token origin/3159-fix-mobile-web origin/HEAD -> origin/master origin/master origin/production origin/staging
The git branch -r command works without an internet connection. It has all the data stored in git objects from the earlier git fetch origin.
remote tracking branches
We can see those objects with ls .git/refs/remotes/origin:
2933-upgrade-factory-girl 3114-add-validations-for-subscription-token 3159-fix-mobile-web HEAD master production staging
These are the "remote branches", or more formally named "remote-tracking branches" in the git man pages, but who has time for that mouthful when serving and protecting the general populace?
The more formal name is clearer because the remote branches are not the actual remote's branches. They are like pointers or bookmarks to origin's branches.
naming convention
The naming convention of ticket-number-verb-noun is nice for quickly finding things and tab completing. For example: git branch -r | ack 2933 outputs:
origin/2933-upgrade-factory-girl
For more on ack, see betterthangrep.com.
When a teammate asks us to review their code on "ticket 2933", we could:
git fetch git diff origin/master..`git branch -r | ack 2933`
However, that's only the diff without syntax highlighting. Github is better for this.
We can do better by using the number to check out a new tracking branch:
git checkout `git branch -r | ack 2933 | sed 's/.*\///'` Switched to branch '2933-upgrade-factory-girl' Your branch is behind 'origin/2933-upgrade-factory-girl' by 1 commit, and can be fast-forwarded
We're too busy fighting crime to type that again. So, we abstract it to a script:
#!/bin/sh code-review() { branch=`git branch -r | ack $1 | sed 's/.*\///'` git checkout $branch }
Now, we can code-review 2933 or even code-review 3159, which creates a new branch and immediately tracks origin/3159-fix-mobile-web.
local machine code reviews
Github pull requests for feature branch code reviews have benefits:
People can review code at the same time (parallel processing).
People can comment at the line level (good for discussion).
However, code reviews on our local machines have benefits, too:
Run tests after checkout so they run while you review (parallel processing).
Read surrounding context of the diff in your editor (faster understanding).
Make small changes yourself, without relaying to the original author things like "formatting", "spelling", "parentheses" in comments (faster fixes).
Use the app, perhaps in a web browser. (smoke test it works as intended).
squash
While helping our teammates is part of the job, we have our own beat (our own feature branches) to finish and send for a code review.
We've been working on a feature that adds the Chosen plugin to an admin screen, which required about an hour of overriding styles with !important.
The code now works, passes tests, and looks great in a browser. We're almost ready for a code review.
We've been making many small commits in our feature branch as we wrote the feature but to be nice guys toward the reviewer, we squash the commits down to one good commit message:
git checkout 4000-use-chosen-in-admin-section git rebase -i origin/master
The -i flag is an interactive rebase, and opens ourEDITOR with:
pick 28e91bb [#4000] Add Chosen as Javascript asset pick 2043850 [#4000] Link to Chosen stylesheet in admin layout pick fd38b60 [#4000] Add Chosen to select field pick 34c2e5c [#4000] Fix Chosen formatting # Rebase 19780cc..34c2e5c onto 19780cc # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted.
The comment tells us what to do but we're no rookies: been doing this for years!
Fingers like lightning, we squash it down:
pick 28e91bb [#4000] Add Chosen as Javascript asset squash 2043850 [#4000] Link to Chosen stylesheet in admin layout squash fd38b60 [#4000] Add Chosen to select field
Since we didn't actually change anything, we don't feel the need to run the tests again and just force push to origin:
git push -f
We ask a teammate for a code review. They oblige.
A few minutes later, they surprise us with a question:
> Did you forget to commit some files?
Confused, we check the commit.
To our horror, we realize we accidentally dd'ed in vim the time-consuming commit that we don't think we can easily re-write.
To make matters even worse, with the interactive rebase, we re-wrote the git history! When we force pushed, we overwrote the clone on origin!
Our families start screaming: "We're burning alive! I can't feel my legs!" Here comes the meatwagon: "Whee-ooh! Whee-ooh!" The medic gets out and says Oh. My. God. New guy's in the corner puking his guts out: "Bleah! Bleah!"
reflog
Just then, your grizzled old partner calmly types git reflog into the shell:
df83012 HEAD@{0}: checkout: moving from 4000-use-chosen-in-admin-section to df83012 3bc02a4 HEAD@{1}: commit (amend): [#4000] Use Chosen in admin section 9dd0667 HEAD@{2}: rebase -i (squash): [#4000] Add Chosen to select field 9dd0667 HEAD@{3}: rebase -i (squash): [#4000] Link to Chosen stylesheet in admin layout 7d14c9d HEAD@{4}: rebase -i (pick): [#4000] Add Chosen as Javascript asset 7a0ed21 HEAD@{5}: rebase -i (squash): updating HEAD 19780cc HEAD@{6}: checkout: moving from 2933-upgrade-factory-girl to 19780cc47583778009f7a2c4b52dbb50bda1d78f b6fd856 HEAD@{7}: commit: [#4000] Fix Chosen formatting
He copies the SHA1 hash and types git merge b6fd856, then git log:
9eaa992 [2 seconds ago] Merge commit 'b6fd856' into 4000-use-chosen-in-admin section
Whoa. That was close.
We make a mental note to run tests after future rebases and before force pushes, for reflog is an option of last resort, like a union lawyer.
prune
Before we end our shift, we git remote prune origin:
- [deleted] 3159-fix-mobile-web
The manual explains:
> Deletes all stale remote-tracking branches under origin. These stale branches have already been removed from the remote repository referenced by origin, but are still locally available in remotes/origin.
So, it looks like 3159 was merged in or deleted on origin by another teammate.
Works for us. Let's go for a taste.
Fake movie poster by Kyle Fiedler. For more posters, see Team Rotations.
Written by Dan Croak.