From 2afd1033f5193102a2480f8ec88dcf46ccb795af Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 15 Mar 2012 16:44:43 -0500 Subject: import a bunch of mjd's git helper scripts --- bin/git/git-re-edit | 25 +++++++++++++++++ bin/git/git-treehash | 27 ++++++++++++++++++ bin/git/git-vee | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100755 bin/git/git-re-edit create mode 100755 bin/git/git-treehash create mode 100755 bin/git/git-vee (limited to 'bin/git') diff --git a/bin/git/git-re-edit b/bin/git/git-re-edit new file mode 100755 index 0000000..7172acd --- /dev/null +++ b/bin/git/git-re-edit @@ -0,0 +1,25 @@ +#!/usr/bin/perl +# +# Still fails when files may contain spaces +# +# Run the editor on all the files that have been modified from the +# current index. Useful to resume work when you left the working tree +# dirty. Useful following a "git reset HEAD^" to continue work on the +# stuff you were working on before. Useful following a failed merge. +# + +chomp(my @changed = qx{git status --porcelain}); +exit 1 unless $? == 0; +s/^.. // or die "<$_>???\n" for @changed; +die "Fucking shell, how does it work?\n" + if grep / /, @changed; + +@changed = qw(.) unless @changed; +chomp(my @lines = qx{find @changed -type f }); +exit 1 unless $? == 0; + +# maybe should use output of "git var GIT_EDITOR" here? +# But then I have to involve the !@&*!@*(&!@ shell +my $ed = $ENV{VISUAL} || $ENV{EDITOR} || "emacs"; +exec $ed, @lines; +die "exec $ed: $!\n"; diff --git a/bin/git/git-treehash b/bin/git/git-treehash new file mode 100755 index 0000000..8b2d1a4 --- /dev/null +++ b/bin/git/git-treehash @@ -0,0 +1,27 @@ +#!/usr/bin/perl + +my %opt; +use Getopt::Std; +getopts("q", \%opt); + +@ARGV = qw(HEAD ORIG_HEAD) unless @ARGV; + +for my $rev (@ARGV) { + chomp(my $res = qx{git rev-parse $rev^{tree}}); + if ($?) { $BAD++ } + else { push @{$hash{$res}}, $rev } +} + +exit 2 if $BAD; +if (keys(%hash) == 1) { + my ($res) = keys %hash; + print "$res\n" unless $opt{"q"}; + exit 0; +} else { + unless ($opt{"q"}) { + for my $res (keys %hash) { + print $res, " ", join(" ", @{$hash{$res}}), "\n"; + } + } + exit 1; +} diff --git a/bin/git/git-vee b/bin/git/git-vee new file mode 100755 index 0000000..d42dce3 --- /dev/null +++ b/bin/git/git-vee @@ -0,0 +1,78 @@ +#!/bin/sh +# +# This prepares a brief summary of how your current branch has diverged +# from a corresponding remote branch. A typical use is: +# git vee origin +# +# if the currently-checked-out branch is master, this will compare +# master and origin/master. +# +# It uses git log --cherry-mark, so you need at least git 1.4.7.1. +# If --cherry-mark doesn't work, delete that option from this script. +# +# Usage: +# git vee # compare current head branch and its remote tracking branch +# git vee remote # compare current head branch and its analog on the remote +# git vee remote branch # compare branch and remote/branch +# git vee branch # compare HEAD and branch +# git vee branch1 branch2 # compare branch1 and branch2 +# + +DIE=false; + +equal_commits () { + [ $(git rev-parse $A) = $(git rev-parse $B) ] +} + +valid_ref () { + git rev-parse -q --verify $1 >/dev/null +} + +is_remote () { + git remote | grep -q "^$1"'$' +} + +die_later () { + echo $* 1>&2; + DIE=true +} + +die_now () { + $DIE && exit 1 +} + +usage () { + echo "Usage: $0 [remote] [branch]" 1>&2 + echo " $0 branch-a [branch-b]" 1>&2 + exit 2 +} + +case $# in + 0) Y=$(git get current-branch-name); + X=$(git get branch-remote $Y); + ;; + 1) X=$1 Y=HEAD;; + 2) X=$1 Y=$2;; + *) usage ;; +esac + +if is_remote $X; then + if [ $Y = HEAD ]; then + Y=$(git get current-branch-name) + fi + A=$Y B="$X/$Y" +else + A=$X; B=$Y; +fi + +valid_ref $A || die_later "$A: unknown commit" +valid_ref $B || die_later "$B: unknown commit" +die_now + +if equal_commits $A $B ; then + echo "$A and $B are identical" + exit 0; +fi + +git log --decorate --cherry-mark --oneline --graph --boundary $A"..."$B + -- cgit v1.2.3-54-g00ecf