Is it possible to create a Git hash object outside a Git directory?

270 views Asked by At

I am trying to get the git diff between 2 strings. The following command works:

git diff $(echo "my first string" | git hash-object -w --stdin) $(echo "my second string" | git hash-object -w --stdin)  --word-diff

However, it fails if not executed inside a Git directory.

I believe this portion of the command is failing:

echo "my first string" | git hash-object -w --stdin

Is there any way around this so that it can be executed outside a Git directory?

2

There are 2 answers

1
Leon On BEST ANSWER

I believe this portion of the command is failing:

echo "my first string" | git hash-object -w --stdin

Is there any way around this so that it can be executed outside a git directory?

The problem you are having is because of the -w option that you pass to the git hash-object command. That option requires an existing repository as it has a side effect of writing the object into the git database.

Proof:

$ echo "my first string" | git hash-object -w --stdin
fatal: Not a git repository (or any parent up to mount point /home)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).

$ echo "my first string" | git hash-object --stdin
3616fdee3ac48e5db02fbf9d5e1c2941cfa3e165

However, since your final goal is to obtain the git diff between two given strings you have to have a git repository if you want to do it with the help of git hash-object1. To this end you can generate a temporary empty repository:

$ tmpgitrepo="$(mktemp -d)"

$ git init "$tmpgitrepo"
Initialized empty Git repository in /tmp/tmp.MqBqDI1ytM/.git/

$ (export GIT_DIR="$tmpgitrepo"/.git; git diff $(echo "my first string" | git hash-object -w --stdin) $(echo "my second string" | git hash-object -w --stdin)  --word-diff)
diff --git a/3616fdee3ac48e5db02fbf9d5e1c2941cfa3e165 b/2ab8560d75d92363c8cb128fb70b615129c63371
index 3616fde..2ab8560 100644
--- a/3616fdee3ac48e5db02fbf9d5e1c2941cfa3e165
+++ b/2ab8560d75d92363c8cb128fb70b615129c63371
@@ -1 +1 @@
my [-first-]{+second+} string

$ rm -rf "$tmpgitrepo"

This approach can be packaged into a bash function:

git-diff-strings()
(
    local tmpgitrepo="$(mktemp -d)"
    trap "rm -rf $tmpgitrepo" EXIT
    git init "$tmpgitrepo" &> /dev/null
    export GIT_DIR="$tmpgitrepo"/.git
    local s1="$1"
    local s2="$2"
    shift 2
    git diff $(git hash-object -w --stdin <<< "$s1") $(git hash-object -w --stdin <<< "$s2") "$@"
)

Usage:

git-diff-strings <string1> <string2> [git-diff-options]

Example:

git-diff-strings "first string" "second string" --word-diff

1 Note that you can git diff two strings by creating 2 temporary files containing those strings, in which case you don't need a git repository.

0
jburtondev On

@danday74 I am unable to write a comment based on your feedback (due to permissions on StackOverflow) so here is my answer. You can set the environment variable using GIT_DIR. If you do this on the multiple machines (you would need to be able to set this variable on such machines), then you will be able to reliably set --git-dir.

Hope this helps.