Bash script for tagging the current git workspace including uncommitted changes I use the following script to autotag the current workspace while building even if there are changed (not committed) files:

#!/bin/bash

tagname="autobuild-test1"
commitname="autocommit for tag $tagname"

set -e
head="`git rev-parse HEAD`"
test -n "$head"
git commit -m "$commitname" -a
taghead="`git rev-parse HEAD`"
git tag "$tagname" "$taghead"
#or just `git tag "$tagname" HEAD` for the 2 lines above
git reset "$head"


The idea: I commit everything which is not committed to a 'temporary commit' and tag its hash. After doing this, I revert to the original state by resetting to the previous HEAD.

In other words: I try to do git commit -a without touching HEAD, staging, stashing and workspace.

Pros:


this also works if the workspace is dirty
the script is very flexible
the script doesn't touch any files, doesn't do any checkout or remove operations


Cons:


the staging state is completely cleared after running the script
probably more state modifications which I didn't find yet
it is a script. I would prefer a single command for this use case
no proper error handling. if the script fails, HEAD might be changed


This script was inspired by cvs2git which uses the same strategy in cases where it's not clear to which revision a tag belongs to.

Is there anything you would change to make this script more rubust and/or to remove some of the cons?
With the input of @EtanReisner, I found a possible way to the solution:

That's our current situation:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD &lt;file&gt;..." to unstage)

    new file:   c
    new file:   e

Changes not staged for commit:
  (use "git add/rm &lt;file&gt;..." to update what will be committed)
  (use "git checkout -- &lt;file&gt;..." to discard changes in working directory)

    deleted:    c
    modified:   e

Untracked files:
  (use "git add &lt;file&gt;..." to include in what will be committed)

    d


I try now to stash all this:

$ git stash --all


Now we can get the hash of it:

$ git rev-parse refs/stash
9a208ed215032b4e47cb1493fc5f16a4a5ea78c1


Or tag it directly (this works)

$ git tag tagged-workspace-01 refs/stash


Now I unstage everything

$ git stash pop --index


This worked quite well:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD &lt;file&gt;..." to unstage)

    new file:   c
    new file:   e

Changes not staged for commit:
  (use "git add &lt;file&gt;..." to update what will be committed)
  (use "git checkout -- &lt;file&gt;..." to discard changes in working directory)

    modified:   e

Untracked files:
  (use "git add &lt;file&gt;..." to include in what will be committed)

    d


As you can see, under some (very unusual) conditions it happens that the revert is not 100% perfect (the not-staged removal of the file c which is also in the index as a new file), but so far it's the best solution I've found.