Showing only posts with label git. See the RSS for this label, or see all posts.

Since this is something I’ve had to figure out 5 times already:

#!/bin/sh

git filter-branch --env-filter '
if [ "$GIT_AUTHOR_EMAIL" = "old-email-address" ];
then
    export GIT_AUTHOR_EMAIL="new-email-address";
fi
' HEAD

… will replace all occurrences of ‘old-email-address’ in the git commit email field with ‘new-email-address’ on the current branch.

The usual caveats of rewriting history apply: your head will diverge and anyone working off your branch is in for a hassle.

William Morgan, April 17, 2011.

[Update 2010-09-20: tweaked to run the grep on the git root instead of whatever directory the current file is in.]

After many months of screwing around with git.vim and fugitive.vim, I have finally found the perfect vim + git grep combination.

This incantation allows you to press <ctrl-x> twice on a symbol and have a minibuf pop up with all the occurrences of that symbol within the project. You can then jump to any occurrence by pressing enter on the corresponding line.

Place this in e.g. ~/.vim/plugin/git-grep.vim:

let g:gitgrepprg="git\\ grep\\ -n"
let g:gitroot="`git rev-parse --show-cdup`"

function! GitGrep(args)
    let grepprg_bak=&grepprg
    exec "set grepprg=" . g:gitgrepprg
    execute "silent! grep " . a:args . " " . g:gitroot
    botright copen
    let &grepprg=grepprg_bak
    exec "redraw!"
endfunction

func GitGrepWord()
  normal! "zyiw
  call GitGrep(getreg('z'))
endf
nmap <C-x><C-x> :call GitGrepWord()<CR>

William Morgan, August 20, 2010.

I’ve released git-wtf version bf06ab7. The highlight of this release is colorized output. ANSI escape sequences are the future of the web.

Also, the feature / integration branch comparisons is now only displayed when -r is supplied.

Check out the git-wtf home page for an example of the fancy colorization, or just download it now.

William Morgan, July 28, 2009.

I’ve released version 58b87fe9 of git-wtf, available here: http://git-wt-commit.rubyforge.org/git-wtf

This version contains a fairly major change: branches on origin are treated as equal to local branches, and branches that are remote-only are denoted with { }. So now there are three possible symbols: ( ) for local-only, { } for remote-only, and [ ] for branches that appear on both origin and your local repo.

The motivation was dealing with the fact that Sup has very many feature branches going at once, but I work on it on several different computers and typically only have a subset of them checked out. I didn’t want anyone to be left out….

I also fixed a few minor things like removing the restriction that version branches be local branches.

William Morgan, May 1, 2009.

Development of Sup is done with Git. Sup follows a topic branch methodology: features and bugfixes typically start off as “topic” branches from master, and are merged into an “integration”/“version” branch next for integration testing. After n cycles of additional bugfix commits to the topic branch, and re-merges into next, the topic branches are finally merged down to master, to be included in the next release.

I really like this approach because I think it evinces the real power of Git: that merges are so foolproof that I can pick and choose, on a feature-by-feature basis, which bits of code I want at each level of integration. That’s crazy cool. And users can stick to master if they want something stable, and next if they want the latest-and-greatest features.

The biggest problem I’ve had, though, is that long-lived topic branches often conflict with each other. This happens both when merging into next and when merging into master. I don’t think there’s a way around it; isolating features in this way has all the benefits above, but it also means that when they touch the same bits of code, you’ll get a conflict.

As a lazy maintainer, the biggest question I’ve had is: is there a way to push the burden of conflict resolution to the patch submitter? Is there a way for me to say: hey, your change conflicts with Bob’s. Can you resolve the conflict and send it to me?

One option I’ve considered is to have contributors to publish not only their feature branches, but their next branch as well. Assuming they aren’t mucking about with their next branch otherwise, if it contains just the merge commit, I can merge it into mine, and it should be a fast-forward that gets me the merge commit, conflict resolution and all.

But I don’t like that idea because, in every other case, I’m merging in the feature branches directly. Why should I suddenly start merging in next just because you have a conflict?

Furthermore, Sup primarily receives email contributions via git format-patch, and I do the dirty deed of sorting them into branches and merging things around. Requiring everyone to host a git repo iff they produce a conflicting patch seems silly. (And git format-patch, unfortunately, produces nothing for merge commits, even if they have conflict resolution changes. Maybe there’s a good reason for this, or maybe not. I’m not sure.)

After some effort, and some git-talk discussion, I have a solution. And no, it doesn’t involve sharing git-rerere caches. (Which it seems that some people do!)

For the contributor: once you have resolved the conflict, do a git diff HEAD^. This will output the conflict resolution changes. Email that to the maintainer along with your patch.

For the maintainer:

$ git checkout next
$ git merge <offending branch>
[... you have a conflict, yada yada ...]
$ git checkout next .
$ git apply --index <resolution patch filename>
$ git commit

Running git merge gets you to the point where you have a conflict. Running git checkout next . sets your working directory to the state it was before you merged. And git apply applies the resolution changes.

You lose authorship of the conflict resolution, but you can use git commit --author to set it.

I think the ideal solution would be for git format-patch to produce something usable in this case. I see some traffic on the Git list that suggests this is being considered, so hopefully one day this rigmarole will not be necessary.

William Morgan, March 22, 2009.

I’ve released a version dd706855 of git-wtf, available here: http://git-wt-commit.rubyforge.org/git-wtf

I’ve tweaked the output format so that branches that don’t exist on the remote server are displayed with ()‘s and those that do with []’s, and ~ is the new symbol for a merge that only occurs on the local side.

I think this produces a better display; lots more information per line of ourput.

I’ve also added a couple random options which you can discover by reading the source. :)

The big next step I’d like to take with this thing is to support multiple remote repos better. Currently it’s kinda specific to your origin repo.

William Morgan, March 16, 2009.

Some git-fu I’ve been finding particularly useful recently:

  1. Untangling concurrent changes into multiple commits: git add -p is the greatest thing since sliced bread. But did you know it features an ‘s’ command which allows you to split a hunk into smaller hunks? Now you can untangle pretty much anything.
  2. Splitting a previous commit into multiple commits: I’ve been finding this one useful for quite a while. Start with a git rebase -i, mark the commit(s) as edit, and once you get there, do a git reset HEAD^. All the changes in that commit will be moved out of the staging area, and you can git add/git commit to your heart’s content. Finish with a quick git rebase --continue to the throat.
  3. Fixing your email address in previous commits: I often make a new repo and forget to change my email address. (For historical, and now silly, reasons, I like to commit to different projects from different addresses, and I often screw it up.) Here’s how to do a mass change: git filter-branch --env-filter "export GIT_AUTHOR_EMAIL=your.new.email.address" commit..HEAD, where commit is the first commit to be affected. Of course, changing the email address of a commit changes its id (and the id of all subsequent commits), so be careful if you’ve published them. (Also note that using --env-filter=... won’t work. No equal sign technology.)
  4. A git log that includes a list of files modified by each commit: git log --stat, which also gives you a colorized nice histogram of additions/deletions for each file. This is a nice middle ground between git log and git log -p.
  5. Speaking of git log -p, here’s how to make it sane in the presence of moves or renames: git log -p -C -M. Otherwise it doesn’t check for moves or copies, and happily gives you the full patch. (These should be on by default.)
  6. Comparing two branches: you can use git log --pretty=oneline one..two for changes in one direction (commits that ‘two’ has that ‘one’ doesn’t); and two..one for the opposite direction. You can also use the triple-dot operator to merge those two lists into one, but typically I find it useful to separate the two. Or you can check out git-wtf, which does this for you.
  7. Preview during commit message: git commit -v will paste the diff into your editor so you can review it while composing the commit message. (It won’t be included in the final message, of course.)
  8. gitk: don’t use it. You’ll get obsessive about merge commits, rebasing, etc., and it just doesn’t matter in the end. It took me about 4 months to recover from the bad mindset that gitk put me into.
William Morgan, October 28, 2008.

Git 1.6.0 (just released) contains now detects Ruby class, module and method definitions in diff output. Previously it was just class names. (This patch.)

Other things I’m excited about in the new Git:

  1. git-clone --mirror is a handy way to set up a bare mirror repository.
  2. git-diff --check now checks for leftover merge conflict markers.
  3. git-stash save now has a —keep-index option. This lets you stash away the local changes and bring the changes staged in the index to your working tree for examination and testing.
  4. git-stash also has a new branch subcommand to create a new branch out of stashed changes.
William Morgan, August 19, 2008.

I’ve fleshed out ditz plugin architecture and just added a plugin that ties it more closely to git. With this plugin enabled, you can tie issues to feature branches and automatically get a list of commits on that branch (until they’re merged into master, at which point that becomes impossible, thanks to the magic of git).

Here’s an example: Sup’s configurable colors issue.

With these changes, Ditz is now firmly in the MVC camp. The models are created from yaml objects on disk; the views are an HTML renderer (using ERB) and a screen renderer (using puts technology), and the controller is the previously-mentioned operator.rb.

If you look at the plugin code you see that it need to modify all three of these components. It adds fields to the Issue and Config objects, it adds output to the HTML and screen views, and it adds commands to the controller. The fact that it can do this in a few lines of code is pretty sweet.

William Morgan, June 26, 2008.

I’ve released a fairly preliminary version of git-wtf to my collection of Git tools. This is something I’ve been working on recently to help wean myself away from excessive gitk usage. From the description:

If you’re on a feature branch, it tells you which version branches it’s merged into. If you’re on a version branch, it tells you which feature branches are merged in and which aren’t. For every branch, if it’s a tracking branch, it tells you which commits need to be pulled and which need to be pushed.

So basically if you find yourself with a ton of branches (which invariably happens if you use feature branches in Git) or you find that keeping track of branch state is generally hard, and that gitk is confusing as often as it is useful, this is the tool for you.

By default it assumes that any branches named “master”, “next” or “edge” are version branches, and all other branches are feature branches. This is configurable, of course. It also warns, for tracked branches, if both the remote branch and the local branch have new commits, i.e. git pull would create a merge commit and you should rebase instead. If you don’t care about this type of thing, this might be annoying.

The main thing addition I foresee in the near future is a warning if merging in a feature branch into a version branch would collapse two version branches. Something like: when merging a feature branch into a version branch, warn if the feature branch contains commits reachable from any version branch and not reachable from master.

William Morgan, June 26, 2008.