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

inotify daemon speedup for git [POC/HACK]

From
Finn Arne Gangstad <finnag@pvv.org>
Date
Jul 27, 2010, 12:20 UTC
Message-ID
<20100727122018.GA26780@pvv.org>

Reading through the thread about subtree I noticed Avery mentioning using inotify to speed up git status & co.

Here is a quick hack I did some time ago to test this out, to use it call "igit" instead of "git" for all commmands you want to speed up.

There is one minor nit: The speedup gain is zero :) git still traverses all directories to look for .gitignore files, which seems to totally kill the optimisation.

To use it, put igit and git-inotify-daemon.pl in path, and do git config core.ignorestat=true in the repositories you want to test it with. The igit wrapper will run git update-index --no-assume-unchanged on all modified files before running any real git commands.

To get inotify to ignore all changes that the git commands themselves perform, the "igit" wrapper kills the currently running daemon. Then it reads the list of updates files, and does git-update-index --no-assume-unchanged on them. Then the git command is run, and finally the daemon is fired up again.

I had to do one tiny modification to git to make update-index ignore bad paths.

igit - a git wrapper with an inotify daemon
Linux only - requires inotifytools installed. This is juct a quick hack/proof
of concept!
update-index: Do not error out on bad paths, just warn
---
 .gitignore             |    1 +
 builtin/update-index.c |    2 +-
 git-inotify-daemon.pl  |   28 ++++++++++++++++++++++++++++
 igit                   |   22 ++++++++++++++++++++++
 4 files changed, 52 insertions(+), 1 deletions(-)
 create mode 100755 git-inotify-daemon.pl
 create mode 100755 igit
diff --git a/.gitignore b/.gitignore
index 14e2b6b..fa67132 100644
--- a/.gitignore
+++ b/.gitignore
@@ -204,3 +204,4 @@
 *.pdb
 /Debug/
 /Release/
+.igit-*
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 3ab214d..c905d78 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -282,7 +282,7 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
 	}
 	if (mark_valid_only) {
 		if (mark_ce_flags(p, CE_VALID, mark_valid_only == MARK_FLAG))
-			die("Unable to mark file %s", path);
+			fprintf(stderr, "Unable to mark file %s\n", path);
 		goto free_return;
 	}
 	if (mark_skip_worktree_only) {
diff --git a/git-inotify-daemon.pl b/git-inotify-daemon.pl
new file mode 100755
index 0000000..a57ceef
--- /dev/null
+++ b/git-inotify-daemon.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+# Run from igit
+
+use warnings;
+use strict;
+
+die "Usage: $0 <output-file>" unless $#ARGV == 0;
+my $output = $ARGV[0];
+my $pid = open(INOTIFY, "exec inotifywait -q --monitor --recursive --exclude .git -e attrib,moved_to,moved_from,move,create,delete,modify --format '%w%f' .|") or die "Cannot run inotifywait: $!\n";
+
+$| = 1;
+print "$pid\n";
+
+my %modified_files;
+while (<INOTIFY>) {
+    s=^./==;
+    chomp;
+    $modified_files{$_} = 1;
+}
+
+# Output file must be opened as late as possible, it is a named pipe
+# and the listener won't be here before inotifywait exits.
+# open would just hang if it was done earlier.
+open(OUT, ">$output");
+foreach my $key (sort keys %modified_files) {
+    print OUT "$key\000";
+}
+exit 0;
diff --git a/igit b/igit
new file mode 100755
index 0000000..60c5bb2
--- /dev/null
+++ b/igit
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+TOPDIR=`git rev-parse --show-cdup` || exit 1
+
+if [ ! "$TOPDIR" ]; then
+    TOPDIR="./"
+fi
+
+PIPE=.igit-pipe
+PIDFILE=.igit-pid
+
+if [ -p ${TOPDIR}${PIPE} ] && kill -TERM `cat ${TOPDIR}${PIDFILE}`; then
+    ( cd $TOPDIR && git update-index --verbose --no-assume-unchanged -z --stdin < $PIPE )
+fi
+
+git "$@"
+
+cd $TOPDIR
+rm -f $PIPE
+mkfifo $PIPE
+git-inotify-daemon.pl $PIPE > $PIDFILE 2>> .igit-errors </dev/null &
+
-- 
1.7.2.rc0


- Finn Arne
Next: Avery Pennarun
Message 1 of 18 in “inotify daemon speedup for git [POC/HACK]”
  1. Finn Arne GangstadJul 27, 2010
  2. Avery PennarunJul 27, 2010
  3. Joshua JuranJul 27, 2010
  4. Avery PennarunJul 27, 2010
  5. Shawn O. PearceJul 28, 2010
  6. Avery PennarunJul 28, 2010
  7. Joshua JuranJul 28, 2010
  8. Avery PennarunJul 28, 2010
  9. Sverre RabbelierJul 28, 2010
  10. Jonathan NiederJul 28, 2010
  11. Ævar Arnfjörð BjarmasonJul 28, 2010
  12. Theodore TsoJul 28, 2010
  13. Nguyen Thai Ngoc DuyJul 28, 2010
  14. Enrico WeigeltAug 13, 2010
  15. Jakub NarebskiJul 28, 2010
  16. Jakub NarebskiJul 28, 2010
  17. Enrico WeigeltAug 13, 2010
  18. Sverre RabbelierJul 27, 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.