Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

initial commit

  • Loading branch information...
commit 9d9ae1b21671bde67182d02814568134e8f70184 0 parents
Bart Trojanowski authored November 04, 2009
2  .gitignore
... ...
@@ -0,0 +1,2 @@
  1
+*.swp
  2
+*~
90  README
... ...
@@ -0,0 +1,90 @@
  1
+# About
  2
+
  3
+git-wip is a script that will manage Work In Progress (or WIP) branches.
  4
+WIP branches are mostly throw away but identify points of development
  5
+between commits.  The intent is to tie this script into your editor so
  6
+that each time you save your file, the git-wip script captures that
  7
+state in git.  git-wip also helps you return back to a previous state of
  8
+development.
  9
+
  10
+Latest git-wip can be obtained from [github.com](http://github.com/bartman/git-wip)
  11
+git-wip was written by [Bart Trojanowski](mailto:bart@jukie.net)
  12
+
  13
+# WIP branches
  14
+
  15
+Wip branches are named after the branch that is being worked on, but are
  16
+prefixed with 'wip/'.  For example if you are working on a branch named
  17
+'feature' then the git-wip script will only manipulate the 'wip/feature'
  18
+branch.
  19
+
  20
+When you run git-wip for the first time, it will capture all changes to
  21
+tracked files and all untracked (but not ignored) files, create a
  22
+commit, and make a new wip/*topic* branch point to it.
  23
+
  24
+    --- * --- * --- *          <-- topic
  25
+                     \
  26
+                      *        <-- wip/topic
  27
+
  28
+The next invocation of git-wip after a commit is made will continue to
  29
+evolve the work from the last wip/*topic* point.
  30
+
  31
+    --- * --- * --- *          <-- topic
  32
+                     \
  33
+                      *
  34
+                       \
  35
+                        *      <-- wip/topic
  36
+
  37
+Whne git-wip is invoked after a commit is made, the state of the
  38
+wip/*topic* branch will be reset back to your *topic* branch and the new
  39
+changes to the working tree will be caputred on a new commit.
  40
+
  41
+    --- * --- * --- * --- *    <-- topic
  42
+                     \     \
  43
+                      *     *  <-- wip/topic
  44
+                       \
  45
+                        *
  46
+
  47
+While the old wip/*topic* work is no longer accessible directly, it can
  48
+alwasy be recovered from git-reflog.  In the above example you could use
  49
+`wip/topic@{1}` to access the dangling references.
  50
+
  51
+# git-wip command
  52
+
  53
+The git-wip command can be invoked in several differnet ways.
  54
+
  55
+* `git wip`
  56
+  
  57
+  In this mode, git-wip will create a new commit on the wip/*topic*
  58
+  branch (creating it if needed) as described above.
  59
+
  60
+* `git wip save "description"`
  61
+  
  62
+  Similar to `git wip`, but allows for a custom commit message.
  63
+
  64
+* `git wip log`
  65
+  
  66
+  Show the list of the work that leads upto the last WIP commit.  This
  67
+  is similar to invoking:
  68
+  
  69
+  `git log --stat wip/$branch...$(git merge-base wip/$branch $branch)`
  70
+
  71
+# editor hooking
  72
+
  73
+To use git-wip effectively, you should tie it into your editor so you
  74
+don't have to remember to run git-wip manually.
  75
+
  76
+To add git-wip support to vim add the following to your `.vimrc`.  Doing
  77
+so will make it be invoked after every `:w` operation.
  78
+
  79
+    augroup git-wip
  80
+      autocmd!
  81
+      autocmd BufWritePost * :silent !git wip --editor -- "%"
  82
+    augroup END
  83
+
  84
+The `--editor` option puts git-wip into a special mode that will make it
  85
+more quiet and not report errors if there were no changes made to the
  86
+file.
  87
+
  88
+
  89
+
  90
+<!-- vim: set ft=mkd -->
268  git-wip
... ...
@@ -0,0 +1,268 @@
  1
+#!/bin/sh
  2
+#
  3
+# Copyright Bart Trojanowski <bart@jukie.net>
  4
+# 
  5
+# git-wip is a script that will manage Work In Progress (or WIP) branches.
  6
+# WIP branches are mostly throw away but identify points of development
  7
+# between commits.  The intent is to tie this script into your editor so
  8
+# that each time you save your file, the git-wip script captures that
  9
+# state in git.  git-wip also helps you return back to a previous state of
  10
+# development.
  11
+#
  12
+# See also http://github.com/bartman/git-wip
  13
+#
  14
+
  15
+USAGE='[ info | save <message> | log | delete ] [ --editor | --untracked ] [ [--] <file>... ]'
  16
+LONG_USAGE="Manage Work In Progress branches
  17
+
  18
+Commands:
  19
+
  20
+        git wip                   - create a new WIP commit
  21
+        git wip save <message>    - create a new WIP commit with custom message
  22
+        git wip info [<branch>]   - brief WIP info
  23
+        git wip log [<branch>]    - show changes on the WIP branch
  24
+        git wip delete [<branch>] - delete a WIP branch
  25
+
  26
+Options:
  27
+
  28
+        --editor                  - be less verbose, assume called from an editor
  29
+        --untracked               - capture also untracked files
  30
+        --ignored                 - capture also ignored files
  31
+"
  32
+
  33
+SUBDIRECTORY_OK=Yes
  34
+OPTIONS_SPEC=
  35
+. git-sh-setup || . $(git --exec-path)/git-sh-setup || ( echo "git wip needs git to run." ; exit 1 )
  36
+require_work_tree
  37
+
  38
+TMP="$GIT_DIR/.git-wip.$$"
  39
+trap 'rm -f "$TMP-*"' 0
  40
+
  41
+WIP_INDEX="$TMP-INDEX"
  42
+
  43
+WIP_PREFIX=refs/wip/
  44
+WIP_COMMAND=
  45
+WIP_MESSAGE=WIP
  46
+EDITOR_MODE=false
  47
+LS_FILES_EXTRA=
  48
+
  49
+dbg() {
  50
+	if test -n "$WIP_DEBUG"
  51
+	then
  52
+		printf '# %s\n' "$*"
  53
+	fi
  54
+}
  55
+
  56
+cleanup () {
  57
+        rm -f "$TMP-*"
  58
+}
  59
+
  60
+get_work_branch () {
  61
+        ref=$(git symbolic-ref -q HEAD) \
  62
+        || die "git-wip requires a branch"
  63
+
  64
+
  65
+        branch=${ref#refs/heads/}
  66
+        if [ $branch = $ref ] ; then
  67
+                die "git-wip requires a local branch"
  68
+        fi
  69
+
  70
+        echo $branch
  71
+}
  72
+
  73
+get_wip_branch () {
  74
+        return 0
  75
+}
  76
+
  77
+find_changes () {
  78
+        git ls-files --exclude-standard -m $LS_FILES_EXTRA
  79
+}
  80
+
  81
+check_files () {
  82
+        local files=$@
  83
+
  84
+        for f in $files
  85
+        do
  86
+                [ -f "$f" -o -d "$f" ] || die "$f: No such file or directory."
  87
+        done
  88
+}
  89
+
  90
+do_save () {
  91
+        local msg=$1 ; shift
  92
+        local files=$@
  93
+
  94
+        if test ${#files} -eq 0
  95
+        then
  96
+                files=$(find_changes)
  97
+        else
  98
+                check_files $files
  99
+        fi
  100
+
  101
+        dbg "msg=$msg"
  102
+        dbg "files=$files"
  103
+
  104
+        local work_branch=$(get_work_branch)
  105
+        local wip_branch=$WIP_PREFIX$work_branch
  106
+
  107
+        dbg "work_branch=$work_branch"
  108
+        dbg "wip_branch=$wip_branch"
  109
+
  110
+        # enable reflog
  111
+        mkdir -p "$GIT_DIR/logs/$WIP_PREFIX"
  112
+        : >>"$GIT_DIR/logs/$wip_branch"
  113
+
  114
+        if ! work_last=$(git rev-parse --verify $work_branch)
  115
+        then
  116
+                die "'$work_branch' branch has no commits."
  117
+        fi
  118
+
  119
+        dbg "work_last=$work_last"
  120
+
  121
+        if wip_last=$(git rev-parse --quiet --verify $wip_branch)
  122
+        then
  123
+                base=$(git merge-base $wip_last $work_last) \
  124
+                || die "'work_branch' and '$wip_branch' are unrelated."
  125
+
  126
+                if [ $base = $work_last ] ; then
  127
+                        wip_parent=$wip_last
  128
+                else
  129
+                        wip_parent=$work_last
  130
+                fi
  131
+        else
  132
+                wip_parent=$work_last
  133
+        fi
  134
+
  135
+        dbg "wip_parent=$wip_parent"
  136
+
  137
+        new_tree=$( ( rm -f $WIP_INDEX \
  138
+                  && cp -p .git/index $WIP_INDEX \
  139
+                  && export GIT_INDEX_FILE=WIP_INDEX \
  140
+                  && git read-tree -m $wip_parent \
  141
+                  && git add $files \
  142
+                  && git write-tree \
  143
+                  && rm -f "$WIP_INDEX" ) 
  144
+        ) || die "Cannot save the current worktree state."
  145
+
  146
+        dbg "new_tree=$new_tree"
  147
+
  148
+        if git diff-tree --exit-code --quiet $new_tree $wip_parent ; then
  149
+                say "no changes"
  150
+                $EDITOR_MODE && exit 0
  151
+                exit 1
  152
+        fi
  153
+
  154
+        dbg "... has changes"
  155
+
  156
+        new_wip=$(printf '%s\n' "$msg" | git commit-tree $new_tree -p $wip_parent) \
  157
+        || die "Cannot record working tree state"
  158
+
  159
+        dbg "new_wip=$new_wip"
  160
+
  161
+        git update-ref -m "git-wip: $msg" $wip_branch $new_wip
  162
+
  163
+        dbg "SUCCESS"
  164
+}
  165
+
  166
+do_info () {
  167
+        local branch=$1
  168
+
  169
+        die "info not implemented"
  170
+}
  171
+
  172
+do_log () {
  173
+        local branch=$1
  174
+
  175
+        die "log not implemented"
  176
+}
  177
+
  178
+do_delete () {
  179
+        local branch=$1
  180
+
  181
+        die "delete not implemented"
  182
+}
  183
+
  184
+do_help () {
  185
+        local rc=$1
  186
+
  187
+        cat <<END
  188
+Usage: git wip $USAGE
  189
+
  190
+$LONG_USAGE
  191
+END
  192
+        exit $rc
  193
+}
  194
+
  195
+
  196
+if test $# -eq 0
  197
+then
  198
+        dbg "no arguments"
  199
+
  200
+        do_save "WIP"
  201
+        exit $?
  202
+fi
  203
+
  204
+case "$1" in
  205
+save)
  206
+        WIP_COMMAND=$1
  207
+        shift
  208
+        if [ -n "$1" ]
  209
+        then
  210
+                WIP_MESSAGE=$1
  211
+                shift
  212
+        fi
  213
+        ;;
  214
+info|log|delete)
  215
+        WIP_COMMAND=$1
  216
+        shift
  217
+        ;;
  218
+help)
  219
+        do_help 0
  220
+        ;;
  221
+--*)
  222
+        ;;
  223
+*)
  224
+        [ -f "$1" ] || die "Unknow command '$1'."
  225
+        ;;
  226
+esac
  227
+
  228
+while test $# != 0
  229
+do
  230
+        case "$1" in
  231
+        --editor)
  232
+                EDITOR_MODE=true
  233
+                ;;
  234
+
  235
+        --untracked|--ignored)
  236
+                LS_FILES_EXTRA="$LS_FILES_EXTRA $1"
  237
+                ;;
  238
+
  239
+        --)
  240
+                shift
  241
+                break
  242
+                ;;
  243
+        *)
  244
+                [ -f "$1" ] && break
  245
+                die "Unknow option '$1'."
  246
+                ;;
  247
+        esac
  248
+        shift
  249
+done
  250
+
  251
+case $WIP_COMMAND in
  252
+save)
  253
+        do_save "$WIP_MESSAGE" $@
  254
+        ;;
  255
+info)
  256
+        do_info $@
  257
+        ;;
  258
+log)
  259
+        do_log $@
  260
+        ;;
  261
+delete)
  262
+        do_delete $@
  263
+        ;;
  264
+*)
  265
+        usage
  266
+        exit 1
  267
+        ;;
  268
+esac

0 notes on commit 9d9ae1b

Please sign in to comment.
Something went wrong with that request. Please try again.