3

I sometimes work with two sibling directories both containing the same repository. Using

git remote add sibling ../the-other-directory

I take over changes simply via

git fetch sibling
git cherry-pick sibling/a-branch

This is pretty practical, however I have a concern regarding hardlinks:

If the repositories share files, then crashing one of them could crash the other as well. A broken repository is something I've already experienced and I'm sure that saving a few megabytes and a few milliseconds is just not worth it.

  • Does git use hardlinks when fetching from a repository on the same partition?
  • If so, is there a way of preventing this (like --no-hardlinks for git-clone)?

An additional advantage of not using hardlinks is having an additional backup which gets updated often without any effort.

Leon
  • 31,443
  • 4
  • 72
  • 97
maaartinus
  • 44,714
  • 32
  • 161
  • 320

2 Answers2

1

Git uses hard-links when you clone, but does not when you fetch. That is, when you add your remote via git remote add foo ../somewhere and then git fetch foo, you get copies, not hard-links.

j6t
  • 9,150
  • 1
  • 15
  • 35
1

Testing with the following script suggests that pseudo-cloning via git init + git remote add + git fetch doesn't create hardlinks to the source repository:

hardlinktest:

#!/usr/bin/env bash
tmpdir="$(mktemp -d)"
trap "rm -rf $tmpdir" EXIT
cd "$tmpdir"
set -x
git clone https://github.com/dictcp/awesome-git testrepo
git clone testrepo testrepo.localclone
mkdir testrepo.pseudoclone
cd testrepo.pseudoclone
git init
git remote add sibling ../testrepo
git fetch sibling
cd ..
ls -1 -i testrepo*/.git/objects/a0

Relevant part of the output:

$ ls -1 -i testrepo*/.git/objects/a0
testrepo/.git/objects/a0:
417590 cdfa472f2bf8212a02a3edeb941868d651749d

testrepo.localclone/.git/objects/a0:
417590 cdfa472f2bf8212a02a3edeb941868d651749d

testrepo.pseudoclone/.git/objects/a0:
537341 cdfa472f2bf8212a02a3edeb941868d651749d

This means that the file testrepo.localclone/.git/objects/a0/cdfa472f2bf8212a02a3edeb941868d651749d is a hardlink to testrepo/.git/objects/a0/cdfa472f2bf8212a02a3edeb941868d651749d - their inode values are the same (417590 for my test run, but your mileage will of course vary). The inode value (537341) of the corresponding file in the testrepo.pseudoclone repository tells us that it is an independent copy.

Full output:

$ ./hardlinktest 
+ git clone https://github.com/dictcp/awesome-git testrepo
Cloning into 'testrepo'...
remote: Counting objects: 58, done.
remote: Total 58 (delta 0), reused 0 (delta 0), pack-reused 58
Unpacking objects: 100% (58/58), done.
Checking connectivity... done.
+ git clone testrepo testrepo.localclone
Cloning into 'testrepo.localclone'...
done.
+ mkdir testrepo.pseudoclone
+ cd testrepo.pseudoclone
+ git init
Initialized empty Git repository in /tmp/tmp.ZWoH0OTA1P/testrepo.pseudoclone/.git/
+ git remote add sibling ../testrepo
+ git fetch sibling
remote: Counting objects: 58, done.
remote: Compressing objects: 100% (40/40), done.
remote: Total 58 (delta 17), reused 0 (delta 0)
Unpacking objects: 100% (58/58), done.
From ../testrepo
 * [new branch]      master     -> sibling/master
+ cd ..
+ ls -1 -i testrepo/.git/objects/a0 testrepo.localclone/.git/objects/a0 testrepo.pseudoclone/.git/objects/a0
testrepo/.git/objects/a0:
417590 cdfa472f2bf8212a02a3edeb941868d651749d

testrepo.localclone/.git/objects/a0:
417590 cdfa472f2bf8212a02a3edeb941868d651749d

testrepo.pseudoclone/.git/objects/a0:
537341 cdfa472f2bf8212a02a3edeb941868d651749d
+ rm -rf /tmp/tmp.ZWoH0OTA1P
Leon
  • 31,443
  • 4
  • 72
  • 97