git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Question about .git/objects/info/alternates

From
Chris Packham <judge.packham@gmail.com>
Date
Mar 24, 2010, 18:53 UTC
Message-ID
<a038bef51003241153g33445607qb3ab750e08b0584@mail.gmail.com>
In-Reply-To
<20100323024223.GA12257@progeny.tock>
On Mon, Mar 22, 2010 at 7:42 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:
Show 18 quoted lines
> Chris Packham wrote:
>
>> I would like to have base somehow find the objects it doesn't have in
>> its object store and either download them or just copy them from the
>> object store of projecta.
> [...]
>> From reading [2] I think 'rm
>> .git/objects/info/alternates && git repack -a' might do the trick but
>> I'm not sure.
>
> Almost.  Try ‘git repack -a && rm .git/objects/info/alternates’ instead. :)
>
> (Please back up the repository or try with something less important
> first, since I am not sure.)
>
> Hope that helps,
> Jonathan
>
git repack -a did the correct thing.

It occurs to me that the UI around alternates is a bit lacking i.e. there isn't a git command to display the alternates in use or to add them to an existing repository (or at least I couldn't find one skimming the docs or googling). So here's my attempt to add a 'git alternates' command which can display, add or remove an alternate. The adding and removing could be done with standard shell commands but I've found the recursive displaying quite useful and couldn't think of a simple command line to achieve the same thing .

------8<------
From a5c64de20937da132376d717f19a1d52b54701d2 Mon Sep 17 00:00:00 2001
From: Chris Packham <judge.packham@gmail.com>
Date: Wed, 24 Mar 2010 11:34:11 -0700
Subject: [PATCH] Add git alternates command
Provides a friendlier UI for displaying and configuring alternates.
Signed-off-by: Chris Packham <judge.packham@gmail.com>
---

This patch assumes multiple alterates are possible. If this is not correct then it could be simplfied as there would be no need for walk_alternates.

 Makefile          |    1 +
 git-alternates.sh |  159 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 160 insertions(+), 0 deletions(-)
 create mode 100755 git-alternates.sh
diff --git a/Makefile b/Makefile
index 3a6c6ea..1a7b084 100644
--- a/Makefile
+++ b/Makefile
@@ -334,6 +334,7 @@ TEST_PROGRAMS_NEED_X =
 unexport CDPATH

 SCRIPT_SH += git-am.sh
+SCRIPT_SH += git-alternates.sh
 SCRIPT_SH += git-bisect.sh
 SCRIPT_SH += git-difftool--helper.sh
 SCRIPT_SH += git-filter-branch.sh
diff --git a/git-alternates.sh b/git-alternates.sh
new file mode 100755
index 0000000..74ec707
--- /dev/null
+++ b/git-alternates.sh
@@ -0,0 +1,159 @@
+#!/bin/sh
+#
+# This file is licensed under the GPL v2
+#
+
+USAGE='[-r|--recursive] [-a|--add <dir>] [-f|--force -d|--delete <dir>]'
+
+. git-sh-setup
+
+#
+# Runs through the alternates file calling the callback function $1
+# with the name of the alternate as the first argument to the callback
+# any additional arguments are passed to the callback function.
+#
+walk_alternates()
+{
+    local alternates=$GIT_DIR/objects/info/alternates
+    local callback=$1
+    shift
+
+    if [ -e $alternates ]; then
+        while read line
+        do
+            $callback $line $*
+        done < $alternates
+    fi
+}
+
+#
+# Walk function to display one alternate object store and, if the user
+# has specified -r, recursively call show_alternates on the git
+# repository that the object store belongs to.
+#
+show_alternates_walk()
+{
+    say "Object store $1"
+    say "    referenced via $GIT_DIR"
+
+    local new_git_dir=${line%%/objects}
+    if [ "$recursive" == "true" -a "$GIT_DIR" != "$new_git_dir" ]
+    then
+        GIT_DIR=$new_git_dir show_alternates
+    fi
+}
+
+show_alternates()
+{
+    walk_alternates show_alternates_walk
+}
+
+#
+# Walk function to check that the specified alternate does not
+# already exist.
+#
+check_current_alternate_walk()
+{
+    if test "$1" = "$2"; then
+        die "fatal: Object store $2 is already used by $GIT_DIR"
+    fi
+}
+
+add_alternate()
+{
+    if test ! -d $dir; then
+        die "fatal: $dir is not a directory"
+    fi
+
+    walk_alternates check_current_alternate_walk $dir
+
+    # At this point we know that $dir is a directory that exists
+    # and that its not already being used as an alternate. We could
+    # go further and verify that $dir has valid objects.
+
+    # if we're still going we can safely add the alternate
+    touch $GIT_DIR/objects/info/alternates
+    echo "$(readlink -f $dir)" >> $GIT_DIR/objects/info/alternates
+    say "$dir added as an alternate"
+    say "     use 'git repack -adl' to remove duplicate objects"
+}
+
+rewrite_alternates()
+{
+    if test "$1" != "$2"; then
+        echo $2 >> $3
+    fi
+}
+
+del_alternate()
+{
+    if test ! $force = "true"; then
+        say "Not forced, use"
+        say "   'git repack -a' to fetch missing objects, then "
+        say "   '$dashless -f -d $dir' to remove the alternate"
+        die
+    fi
+
+    local alternates=$GIT_DIR/objects/info/alternates
+
+    new_alts_file=$(mktemp $alternates-XXXXXX)
+    touch $new_alts_file
+
+    walk_alternates rewrite_alternates $dir $new_alts_file
+    mv $new_alts_file $alternates
+
+    # save the git from repeatedly reading a 0 length file
+    if test $(stat -c "%s" $alternates) -eq 0; then
+        rm $alternates
+    fi
+}
+
+dir=""
+oper=""
+force="false"
+
+# Option parsing
+while test $# != 0
+do
+    case "$1" in
+        -r|--recursive)
+            recursive="true"
+            ;;
+        -a|--add)
+            if test ! -z "$oper"; then
+                usage
+            fi
+            oper="add"
+            case "$#,$1" in
+                1,*) usage ;;
+                *)   dir=$2; shift ;;
+            esac
+            ;;
+        -d|--delete)
+            if test ! -z "$oper"; then
+                usage
+            fi
+            oper="del"
+            case "$#,$1" in
+                1,*) usage ;;
+                *)   dir=$2; shift ;;
+            esac
+            ;;
+        -f|--force)
+            force="true"
+            ;;
+        -*)
+            usage
+            ;;
+        *)
+            ;;
+    esac
+    shift
+done
+
+# Now go and do it
+case $oper in
+    add) add_alternate ;;
+    del) del_alternate ;;
+    *)   show_alternates ;;
+esac
-- 
1.7.0.3
Previous: Jonathan NiederNext: Jonathan Nieder
Message 3 of 17 in “Question about .git/objects/info/alternates”
  1. Chris PackhamMar 22, 2010
  2. Jonathan NiederMar 23, 2010
  3. Chris PackhamMar 24, 2010
  4. Jonathan NiederMar 24, 2010
  5. Junio C HamanoMar 24, 2010
  6. Chris PackhamMar 24, 2010
  7. Chris PackhamMar 25, 2010
  8. 1/2 Add git alternate commandChris Packham, Mar 25, 2010
  9. Junio C HamanoMar 29, 2010
  10. Chris PackhamMar 31, 2010
  11. 2/2 tests for git alternate commandChris Packham, Mar 25, 2010
  12. Johannes SixtMar 25, 2010
  13. Chris PackhamMar 25, 2010
  14. Miklos VajnaMar 26, 2010
  15. Johannes SixtMar 26, 2010
  16. Stephen BoydMar 24, 2010
  17. Chris PackhamMar 24, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.