On Thu, Feb 10, 2011 at 02:20:15PM -0800, Jason Brooks wrote:

> I am not sure what I am asking, so I thought I would start here.  If I
> knew the name of this operation, I would look for it.  :)
> I have a software deployment that was copied out of a git repository
> but without the .git directories.  Thus, I have no idea what revision
> this deployment is, and I can't run "whatchanged" on it.  Is there a
> method, or script out there that can help me?
> The trouble is, I should have made a branch when I deployed it to at
> least freeze that version.  At the very least so I can rebase and re-
> deploy it again.
> I appreciate any assistance you all can give me...

I can imagine two ways of accomplishing the task.

First, you could exploit the fact Git is able to do "deep greps" through
the history looking for a commit which introduced a particular change to
a file. So, pick a "distinguished" file in your deployment, that is, a
file that has very high chances of being modified in the commit you're
trying to find, then pick a "representative" string from it -- let's
suppose a variable Foo has been renamed to Bar in that commit -- and do

$ git log --pretty=oneline -SBar

This should probably be repeated for all the branches (and tags) found
in the repository (the example above works on a currently checked out
branch) until something worthy is found.
Possibly you will need several trial-and-error rounds until you are
happy with the result.

Next, you could exploit a fact that Git uses crytographic hashes to
identify objects, hence the course of operation could be this:
1) Turn your exported directory into a git repository simply by running
   $ git init .
   in it.
2) Add all the files using `git add .` and commit them using
  `git commit`.

At this point, you have a commit object which references a tree object
which references blobs representing files and other trees representing
subdirectories. The tree object is what we're interested in as we can
now search the original repository for a commit referencing that tree.
I'm not sure what's the best way to do this, but to me it seems that
git-rev-list can be used along with git cat-file.
For instance, to search the line of commits ending with HEAD for a
commit referencing our imaginary tree,
a0d321756bfe1bb35eed539eb99776b6224662b1, we can do this:

$ git rev-list HEAD \
  | while read commit; do git cat-file commit $commit \
    | grep -q '^tree a0d321756bfe1bb35eed539eb99776b6224662b1$' \
      && { echo "Found: $commit"; break; }; done

This supposedly should be repeated for all the branches (and tags)
present in the repository until a matching commit is found.

Another (more brute-force) way to go would be to unpack all the packs
present in the repository (see git unpack-file) and then do
a simplistic recursive grep on the resulting object files:

$ grep -rh '^tree a0d321756bfe1bb35eed539eb99776b6224662b1$' .git

The name of the located file will give a clear hint about what is the
SHA-1 hash of the commit containing our tree.

Note one possible problem though: this method will work if and only if
you did not change any of the exported files, including changing their
executable bit, nor did you add any new files or remove existing files.
Any changes like this will obviously lead to generation of a different
tree SHA-1 hash.
This could be worked around by picking a "representative" file which
contains some sort of "distinguishing" change, which should have been
recorded in the commit we're looking for. Then you could search 
the repository for it in a quite the same way outlined above, yet in a
bit more involved way: first, you need to find a tree object which
references that file, and then the commit object referencing that tree

You received this message because you are subscribed to the Google Groups "Git 
for human beings" group.
To post to this group, send email to git-users@googlegroups.com.
To unsubscribe from this group, send email to 
For more options, visit this group at 

Reply via email to