Search code examples
gitfindrevisionworking-directory

Find Git Revision of a Working Directory Missing the .git Directory


I've got a) a working directory without the .git directory and b) a repository. a is some revision in the middle of the history of b.

How can I find out, which revision a matches in b?

I thought of a shellscript doing a diff from the working directory to all revisions and pick the one with the least (hopefully 0) differences.

That would be a bit raw (and I'm not sure how to do it), is there an easier way?


Solution

  • You could write a script to run diff gitdir workdir | wc -c for each commit. Then you could collate the results and say the commit which has the smallest difference (as measured by wc -c) is the closest commit to the bare working dir.

    Here is what it might look like in Python:

    find_closest_sha1.py:

    #!/usr/bin/env python
    import subprocess
    import shlex
    import sys
    import os
    import operator
    
    gitdir,workdir=map(os.path.realpath,sys.argv[1:3])
    os.chdir(gitdir)
    proc=subprocess.Popen(shlex.split('git rev-list --all'),stdout=subprocess.PIPE)
    shas,err=proc.communicate()
    shas=shas.split()
    head=shas[0]
    data={}
    for sha1 in shas:
        subprocess.Popen(shlex.split('git checkout {s}'.format(s=sha1)),
                              stderr=open('/dev/null')).wait()
        proc=subprocess.Popen(shlex.split('diff {g} {w}'.format(g=gitdir,w=workdir)),
                              stdout=subprocess.PIPE)
        out,err=proc.communicate()
        distance=len(out)
        data[sha1]=distance
    answer=min(data.items(),key=operator.itemgetter(1))[0]
    print('closest match: {s}'.format(s=answer))
    subprocess.Popen(shlex.split('git checkout {h}'.format(h=head)),
                     stderr=open('/dev/null')).wait()
    

    Example:

    % rsync -a gitdir/ workdir/
    % cd workdir
    % git checkout HEAD~10
    HEAD is now at b9fcebf... fix foo
    
    % cd ..
    % /bin/rm -rf workdir/.git
    % find_closest_sha1.py gitdir workdir
    closest match: b9fcebfb170785c19390ebb4a9076d11350ade79