Deleting Unversioned SVN Files

Here’s a silly bash trick that will delete all unversioned SVN files

svn st | grep "^?" | sed s/?[[:space:]]*// | xargs rm -rf

Use with care, obviously. If there’s a more concise method, please let me know.

And here’s how you might use similar commands to apply fmresolve to all conflicted files, and then resolve them.

for f in $(svn st | grep "^C" | sed s/C[[:space:]]*//); do fmresolve $f; done
svn st | grep "^C" | sed s/C[[:space:]]*// | xargs svn resolved

Active Record Model Adapters

I recently refactored some code in iNaturalist that fetches taxon names from external name providers like uBio and the Catalogue of Life. They return names and classification data that are similar but (of course) not identical to ActiveRecord models we use in iNat, so I figured I’d write adapters for them, and I thought a really smart solution would be to subclass the models themselves, simply overriding the attributes with getters that mined a private instance variable holding an XML response from one of the web services. Big mistake. ActiveRecord mixes in all kinds of magic into the models that doesn’t necessarily get passed on to child classes. I ran into all sorts of fun errors and problems until I remembered the Adapter implementation described here, which takes a much more sensible approach: don’t sublcass, and instead hold an internal copy of the adaptee, passing calls to anything you don’t want to override to the adaptee.

Read the rest of this entry »

Git Cheatsheet

It’s small, fast, and github is rad. So I am trying to learn it.

# Setup
git config --global --list
git config --global "Ken-ichi"
git config --global ""
# The colors, children.  Mm-hey
git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto
# Getting Info
git remote -v # Display the remote repository URL
git log # duh
git show COMMIT # equivalent of svn log -r REV_NUM, but with diffs
# Diffing
git diff COMMIT1..COMMIT2 # duh
git whatchanged --since="1 day ago" -p # show changes in date range, commit by commit
git diff $(git rev-list -n1 --before="1 day ago" master) # same as above by by file
git log origin/master..master # show changes between remote and local
# Committing
git add .
git commit -a
# Amending
git commit -a --amend
# Reverting
git reset --hard HEAD # revert everything to HEAD
git checkout path/to/file # reset a single file
git checkout HEAD path/to/file # reset a file you just deleted with git rm
git reset --soft HEAD^ # unstage last commit if you forgot something
git fetch --all && git reset --hard origin/master # reset and overwrite conflicting untracked files
git revert COMMIT # undo the changes in a commit in a new commit
# Checking out previous states
git checkout COMMIT
git checkout master # to get back
# Stashing
git stash # stash changes on this branch so you can switch and work on something else
git stash pop # bring back the stashed changes
# Pushing to another repos
# could be local like /path/to/somewhere 
# or ssh://
git push path/to/repos
git push origin master # if you cloned from a remote named origin
# to switch origins
git remote rm origin
git remote add origin 'path/to/a/bare/repo'
# note that when sharing a repo with others, you will all want to push/pull from a *bare* repo made with 
git clone --bare path/to/repo
# See
# Branching and merging
git branch new_branch && git checkout new_branch # make a new branch and switch to it
git checkout -b new_branch # same as above
git diff master..new_branch # diff two branches
git merge other_branch
git mergetool -t opendiff # resolve conflicts in a merge with FileMerge
git branch --track localbranchname origin/remotebranchname # track a remote branch.  you might need to git fetch before this will work
git push origin local_branch # push local_branch to a remote repo.  Will create new local_branch in remote if not there already
# Collaboration - add an origin, tracking branch, cherry pick
git remote add -f originname git://
git branch --track localbranch originname/remotebranch # or whatever branch you want
git fetch # pull in updates
git checkout master && git cherry-pick [commit]
# Integrating a range of commits from a branch.
# using cherry-pick
git cherry-pick [first commit]..[last commit
# using rebase --onto
git checkout -b integration # create a branch to integrate changes (optional)
git branch -f integration [last commit] # set integration branch to last commit
git checkout -b tmp # create a tmp branch, not sure why this is necessary
git rebase --onto tmp [first commit]~1 integration # replay from 1 before first commit to last commit
# the above will leave you in integration with the range of commits applied. 
# You can then remove tmp and merge/rebase into a more stable branch
# note that in a hierarchical repo network, e.g. there is one authoritative
# repo and several developers have their own forks, it's usually good practice
# to *merge* from the forks into the authoritative repo, and *rebase* from the
# authoritative repo into the forks. Same applies to dev branches / master
# branch.  I think it has something to do with resolving conflicts, though I
# haven't really hit a major issue with it yet.
# Adding a submodule
git submodule init
git submodule add path/to/remote/repo path/to/local/checkout
git submodule update
git commit -m "I just added a submodule"
# Updating a submodule
cd path/to/local/checkout
git pull origin master # or wherever you're pulling from
cd ../back/to/main/repo
git submodule update
git commit -m "I just updated a submodule"