GIT 0.99.9i aka 1.0rc2

Signed-off-by: Junio C Hamano <junkio@cox.net>
diff --git a/.gitignore b/.gitignore
index 328b399..0dd7b9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,7 +42,7 @@
 git-init-db
 git-local-fetch
 git-log
-git-lost+found
+git-lost-found
 git-ls-files
 git-ls-remote
 git-ls-tree
@@ -74,7 +74,6 @@
 git-rebase
 git-receive-pack
 git-relink
-git-rename
 git-repack
 git-request-pull
 git-reset
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index a7121a4..98014f6 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -3,11 +3,11 @@
 
 NAME
 ----
-git-branch - Create a new branch.
+git-branch - Create a new branch, or remove an old one.
 
 SYNOPSIS
 --------
-'git-branch' [<branchname> [start-point]]
+'git-branch' [-d | -D] [<branchname> [start-point]]
 
 DESCRIPTION
 -----------
@@ -19,11 +19,18 @@
 
 OPTIONS
 -------
+-d::
+	Delete a branch. The branch must be fully merged.
+
+-D::
+	Delete a branch irrespective of its index status.
+
 <branchname>::
-	The name of the branch to create.
+	The name of the branch to create or delete.
 
 start-point::
-	Where to create the branch; defaults to HEAD.
+	Where to create the branch; defaults to HEAD. This
+	option has no meaning with -d and -D.
 
 Author
 ------
diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt
index 94b283a..5bff486 100644
--- a/Documentation/git-checkout-index.txt
+++ b/Documentation/git-checkout-index.txt
@@ -18,21 +18,21 @@
 
 OPTIONS
 -------
--u::
+-u|--index::
 	update stat information for the checked out entries in
 	the index file.
 
--q::
+-q|--quiet::
 	be quiet if files exist or are not in the index
 
--f::
+-f|--force::
 	forces overwrite of existing files
 
--a::
+-a|--all::
 	checks out all files in the index.  Cannot be used
 	together with explicit filenames.
 
--n::
+-n|--no-create::
 	Don't checkout new files, only refresh files already checked
 	out.
 
diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt
index b64cd6a..5cf6bd3 100644
--- a/Documentation/git-commit-tree.txt
+++ b/Documentation/git-commit-tree.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-commit-tree' <tree> [-p <parent commit>]\   < changelog
+'git-commit-tree' <tree> [-p <parent commit>]\* < changelog
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-lost+found.txt b/Documentation/git-lost-found.txt
similarity index 93%
rename from Documentation/git-lost+found.txt
rename to Documentation/git-lost-found.txt
index a8cc573..03156f2 100644
--- a/Documentation/git-lost+found.txt
+++ b/Documentation/git-lost-found.txt
@@ -1,13 +1,13 @@
-git-lost+found(1)
+git-lost-found(1)
 =================
 
 NAME
 ----
-git-lost+found - Recover lost refs that luckily have not yet been pruned.
+git-lost-found - Recover lost refs that luckily have not yet been pruned.
 
 SYNOPSIS
 --------
-'git-lost+found'
+'git-lost-found'
 
 DESCRIPTION
 -----------
@@ -31,7 +31,7 @@
 prune', it is still there.
 
 ------------
-$ git lost+found
+$ git lost-found
 [1ef2b196d909eed523d4f3c9bf54b78cdd6843c6] GIT 0.99.9c
 ...
 ------------
diff --git a/Documentation/git-prune-packed.txt b/Documentation/git-prune-packed.txt
index 28a1500..8d96a91 100644
--- a/Documentation/git-prune-packed.txt
+++ b/Documentation/git-prune-packed.txt
@@ -23,6 +23,12 @@
 
 Packs are used to reduce the load on mirror systems, backup engines, disk storage, etc.
 
+OPTIONS
+-------
+-n::
+        Don't actually remove any objects, only show those that would have been
+        removed.
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>
diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt
index e219c6a..7be0cbd 100644
--- a/Documentation/git-read-tree.txt
+++ b/Documentation/git-read-tree.txt
@@ -30,6 +30,10 @@
 -m::
 	Perform a merge, not just a read.
 
+--reset::
+
+        Same as -m except that unmerged entries will be silently ignored.
+
 -u::
 	After a successful merge, update the files in the work
 	tree with the result of the merge.
diff --git a/Documentation/git-rename.txt b/Documentation/git-rename.txt
deleted file mode 100644
index 583cb03..0000000
--- a/Documentation/git-rename.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-git-rename(1)
-=============
-
-NAME
-----
-git-rename - Script used to rename a file, directory or symlink.
-
-
-SYNOPSIS
---------
-'git-rename' <source> <destination>
-
-DESCRIPTION
------------
-This script is used to rename a file, directory or symlink.
-
-The index is updated after successful completion, but the change must still be
-committed.
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-Rewritten by Ryan Anderson <ryan@michonline.com>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
-
diff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.txt
index b716ba1..31ea34d 100644
--- a/Documentation/git-unpack-objects.txt
+++ b/Documentation/git-unpack-objects.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-unpack-objects' [-q] <pack-file
+'git-unpack-objects' [-n] [-q] <pack-file
 
 
 DESCRIPTION
@@ -19,6 +19,10 @@
 
 OPTIONS
 -------
+-n::
+        Only list the objects that would be unpacked, don't actually unpack
+        them.
+
 -q::
 	The command usually shows percentage progress.  This
 	flag suppresses it.
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index 52874c8..fdcb8be 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -60,7 +60,7 @@
 	Directly insert the specified info into the index.
 	
 --index-info::
-        Read index info from stdin.
+        Read index information from stdin.
 
 --chmod=(+|-)x::
         Set the execute permissions on the updated files.        
diff --git a/Documentation/git.txt b/Documentation/git.txt
index a9d47c1..7045f3f 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -262,9 +262,6 @@
 gitlink:git-rebase[1]::
 	Rebase local commits to new upstream head.
 
-gitlink:git-rename[1]::
-	Rename files and directories.
-
 gitlink:git-repack[1]::
 	Pack unpacked objects in a repository.
 
@@ -309,7 +306,7 @@
 gitlink:git-cvsimport[1]::
 	Salvage your data out of another SCM people love to hate.
 
-gitlink:git-lost+found[1]::
+gitlink:git-lost-found[1]::
 	Recover lost refs that luckily have not yet been pruned.
 
 gitlink:git-merge-one-file[1]::
diff --git a/Makefile b/Makefile
index e84acdc..f4a3a33 100644
--- a/Makefile
+++ b/Makefile
@@ -50,12 +50,14 @@
 # Define USE_STDEV below if you want git to care about the underlying device
 # change being considered an inode change from the update-cache perspective.
 
-GIT_VERSION = 0.99.9h
+GIT_VERSION = 0.99.9i
 
-# CFLAGS is for the users to override from the command line.
+# CFLAGS and LDFLAGS are for the users to override from the command line.
 
 CFLAGS = -g -O2 -Wall
+LDFLAGS =
 ALL_CFLAGS = $(CFLAGS)
+ALL_LDFLAGS = $(LDFLAGS)
 
 prefix = $(HOME)
 bindir = $(prefix)/bin
@@ -90,11 +92,11 @@
 	git-applymbox.sh git-applypatch.sh git-am.sh \
 	git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
 	git-merge-resolve.sh git-merge-ours.sh git-grep.sh \
-	git-lost+found.sh
+	git-lost-found.sh
 
 SCRIPT_PERL = \
 	git-archimport.perl git-cvsimport.perl git-relink.perl \
-	git-rename.perl git-shortlog.perl git-fmt-merge-msg.perl \
+	git-shortlog.perl git-fmt-merge-msg.perl \
 	git-svnimport.perl git-mv.perl git-cvsexportcommit.perl
 
 SCRIPT_PYTHON = \
@@ -187,9 +189,11 @@
 	NEEDS_SSL_WITH_CRYPTO = YesPlease
 	NEEDS_LIBICONV = YesPlease
 	## fink
-	ALL_CFLAGS += -I/sw/include -L/sw/lib
+	ALL_CFLAGS += -I/sw/include
+	ALL_LDFLAGS += -L/sw/lib
 	## darwinports
-	ALL_CFLAGS += -I/opt/local/include -L/opt/local/lib
+	ALL_CFLAGS += -I/opt/local/include
+	ALL_LDFLAGS += -L/opt/local/lib
 endif
 ifeq ($(uname_S),SunOS)
 	NEEDS_SOCKET = YesPlease
@@ -211,7 +215,13 @@
 ifeq ($(uname_S),OpenBSD)
 	NO_STRCASESTR = YesPlease
 	NEEDS_LIBICONV = YesPlease
-	ALL_CFLAGS += -I/usr/local/include -L/usr/local/lib
+	ALL_CFLAGS += -I/usr/local/include
+	ALL_LDFLAGS += -L/usr/local/lib
+endif
+ifeq ($(uname_S),NetBSD)
+	NEEDS_LIBICONV = YesPlease
+	ALL_CFLAGS += -I/usr/pkg/include
+	ALL_LDFLAGS += -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib
 endif
 ifneq (,$(findstring arm,$(uname_M)))
 	ARM_SHA1 = YesPlease
@@ -221,7 +231,7 @@
 
 ifndef NO_CURL
 	ifdef CURLDIR
-		# This is still problematic -- gcc does not want -R.
+		# This is still problematic -- gcc does not always want -R.
 		ALL_CFLAGS += -I$(CURLDIR)/include
 		CURL_LIBCURL = -L$(CURLDIR)/lib -R$(CURLDIR)/lib -lcurl
 	else
@@ -369,12 +379,13 @@
 	$(CC) -o $*.o -c $(ALL_CFLAGS) $<
 
 git-%$X: %.o $(LIB_FILE)
-	$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)
+	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 
 git-mailinfo$X : SIMPLE_LIB += $(LIB_4_ICONV)
 $(SIMPLE_PROGRAMS) : $(LIB_FILE)
 $(SIMPLE_PROGRAMS) : git-%$X : %.o
-	$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIB_FILE) $(SIMPLE_LIB)
+	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+		$(LIB_FILE) $(SIMPLE_LIB)
 
 git-http-fetch$X: fetch.o
 git-local-fetch$X: fetch.o
@@ -408,10 +419,10 @@
 	$(MAKE) -C t/ all
 
 test-date$X: test-date.c date.o ctype.o
-	$(CC) $(ALL_CFLAGS) -o $@ test-date.c date.o ctype.o
+	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) test-date.c date.o ctype.o
 
 test-delta$X: test-delta.c diff-delta.o patch-delta.o
-	$(CC) $(ALL_CFLAGS) -o $@ $^
+	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^
 
 check:
 	for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i; done
diff --git a/apply.c b/apply.c
index 3418118..590adc6 100644
--- a/apply.c
+++ b/apply.c
@@ -370,7 +370,7 @@
 	int len;
 
 	ptr = strchr(line, '.');
-	if (!ptr || ptr[1] != '.' || 40 <= ptr - line)
+	if (!ptr || ptr[1] != '.' || 40 < ptr - line)
 		return 0;
 	len = ptr - line;
 	memcpy(patch->old_sha1_prefix, line, len);
@@ -384,7 +384,7 @@
 		ptr = eol;
 	len = ptr - line;
 
-	if (40 <= len)
+	if (40 < len)
 		return 0;
 	memcpy(patch->new_sha1_prefix, line, len);
 	patch->new_sha1_prefix[len] = 0;
@@ -895,7 +895,8 @@
 		static const char binhdr[] = "Binary files ";
 
 		if (sizeof(binhdr) - 1 < size - offset - hdrsize &&
-		    !memcmp(binhdr, buffer + hdrsize, sizeof(binhdr)-1))
+		    !memcmp(binhdr, buffer + hdrsize + offset,
+			    sizeof(binhdr)-1))
 			patch->is_binary = 1;
 
 		if (patch->is_binary && !apply && !check)
diff --git a/commit.c b/commit.c
index 534c03e..ebf4db6 100644
--- a/commit.c
+++ b/commit.c
@@ -536,7 +536,7 @@
 void sort_in_topological_order(struct commit_list ** list)
 {
 	struct commit_list * next = *list;
-	struct commit_list * work = NULL;
+	struct commit_list * work = NULL, **insert;
 	struct commit_list ** pptr = list;
 	struct sort_node * nodes;
 	struct sort_node * next_nodes;
@@ -580,11 +580,12 @@
          * the tips serve as a starting set for the work queue.
          */
 	next=*list;
+	insert = &work;
 	while (next) {
 		struct sort_node * node = (struct sort_node *)next->item->object.util;
 
 		if (node->indegree == 0) {
-			commit_list_insert(next->item, &work);
+			insert = &commit_list_insert(next->item, insert)->next;
 		}
 		next=next->next;
 	}
diff --git a/debian/changelog b/debian/changelog
index 5ea556a..3d90d93 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+git-core (0.99.9i-0) unstable; urgency=low
+
+  * GIT 0.99.9i aka 1.0rc2
+
+ -- Junio C Hamano <junkio@cox.net>  Mon, 14 Nov 2005 18:38:27 -0800
+
 git-core (0.99.9h-0) unstable; urgency=low
 
   * GIT 0.99.9h
@@ -46,6 +52,12 @@
 
  -- Junio C Hamano <junkio@cox.net>  Sun, 30 Oct 2005 15:03:32 -0800
 
+git-core (0.99.9.GIT-2) unstable; urgency=low
+
+  * Build Dependency did not include libexpat-dev.
+
+ -- Junio C Hamano <junkio@cox.net>  Sun, 13 Nov 2005 01:55:34 -0800
+
 git-core (0.99.9.GIT-1) unstable; urgency=low
 
   * Do not scatter txt and html documentation into feature
diff --git a/debian/control b/debian/control
index 8cc527e..ded0a57 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@
 Section: devel
 Priority: optional
 Maintainer: Junio C Hamano <junkio@cox.net>
-Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev|libcurl3-gnutls-dev|libcurl3-openssl-dev, asciidoc (>= 6.0.3), xmlto, debhelper (>= 4.0.0), bc
+Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev|libcurl3-gnutls-dev|libcurl3-openssl-dev, asciidoc (>= 7), xmlto, debhelper (>= 4.0.0), bc, libexpat-dev
 Standards-Version: 3.6.1
 
 Package: git-core
@@ -48,7 +48,7 @@
 
 Package: git-cvs
 Architecture: all
-Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, git-core
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, git-core, cvsps (>= 2.1)
 Suggests: cvs
 Description: The git content addressable filesystem, CVS interoperability
  This package contains 'git-cvsimport', to import development history from
diff --git a/git-branch.sh b/git-branch.sh
index 67f113a..11d52fd 100755
--- a/git-branch.sh
+++ b/git-branch.sh
@@ -102,6 +102,5 @@
 git-check-ref-format "heads/$branchname" ||
 	die "we do not like '$branchname' as a branch name."
 
-leading=`expr "refs/heads/$branchname" : '\(.*\)/'` &&
-mkdir -p "$GIT_DIR/$leading" &&
-echo $rev > "$GIT_DIR/refs/heads/$branchname"
+git update-ref "refs/heads/$branchname" $rev
+
diff --git a/git-clone.sh b/git-clone.sh
index f99e0ad..c09979a 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -9,7 +9,7 @@
 unset CDPATH
 
 usage() {
-	echo >&2 "* git clone [-l [-s]] [-q] [-u <upload-pack>] [-n] <repo> <dir>"
+	echo >&2 "* git clone [-l [-s]] [-q] [-u <upload-pack>] [-n] <repo> [<dir>]"
 	exit 1
 }
 
@@ -98,7 +98,7 @@
 dir="$2"
 # Try using "humanish" part of source repo if user didn't specify one
 [ -z "$dir" ] && dir=$(echo "$repo" | sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*/||g')
-[ -e "$dir" ] && $(echo "$dir already exists."; usage)
+[ -e "$dir" ] && echo "$dir already exists." && usage
 mkdir -p "$dir" &&
 D=$(
 	(cd "$dir" && git-init-db && pwd)
diff --git a/git-core.spec.in b/git-core.spec.in
index 6a482ad..16c6269 100644
--- a/git-core.spec.in
+++ b/git-core.spec.in
@@ -7,9 +7,9 @@
 Group: 		Development/Tools
 URL: 		http://kernel.org/pub/software/scm/git/
 Source: 	http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz
-BuildRequires:	zlib-devel >= 1.2, openssl-devel, curl-devel  %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
+BuildRequires:	zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel  %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Requires:	zlib >= 1.2, rsync, rcs, curl, less, openssh-clients, python >= 2.3, tk >= 8.4
+Requires:	zlib >= 1.2, rsync, rcs, curl, less, openssh-clients, python >= 2.3, expat
 
 %description
 This is a stupid (but extremely fast) directory content manager.  It
@@ -47,6 +47,13 @@
 %description email
 Git tools for sending email.
 
+%package tk
+Summary:        Git revision tree visualiser ('gitk')
+Group:          Development/Tools
+Requires:       git-core = %{version}-%{release}, tk >= 8.4
+%description tk
+Git revision tree visualiser ('gitk')
+
 %prep
 %setup -q
 
@@ -60,9 +67,9 @@
      prefix=%{_prefix} mandir=%{_mandir} \
      install %{!?_without_docs: install-doc}
 
-(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "arch|svn|cvs|email" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
+(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "arch|svn|cvs|email|gitk" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
 %if %{!?_without_docs:1}0
-(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "arch|svn|git-cvs|email" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
+(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "arch|svn|git-cvs|email|gitk" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
 %endif
 
 %clean
@@ -96,6 +103,13 @@
 %{!?_without_docs: %{_mandir}/man1/*email*.1*}
 %{!?_without_docs: %doc Documentation/*email*.html }
 
+%files tk
+%defattr(-,root,root)
+%doc Documentation/*gitk*.txt
+%{_bindir}/*gitk*
+%{!?_without_docs: %{_mandir}/man1/*gitk*.1*}
+%{!?_without_docs: %doc Documentation/*gitk*.html }
+
 %files -f bin-man-doc-files
 %defattr(-,root,root)
 %{_datadir}/git-core/
diff --git a/git-lost+found.sh b/git-lost-found.sh
similarity index 100%
rename from git-lost+found.sh
rename to git-lost-found.sh
diff --git a/git-rename.perl b/git-rename.perl
deleted file mode 100755
index 3b1127b..0000000
--- a/git-rename.perl
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/perl
-#
-# Copyright 2005, Ryan Anderson <ryan@michonline.com>
-#
-# This file is licensed under the GPL v2, or a later version
-# at the discretion of Linus Torvalds.
-
-
-use warnings;
-use strict;
-
-sub usage($);
-
-# Sanity checks:
-my $GIT_DIR = $ENV{'GIT_DIR'} || ".git";
-
-unless ( -d $GIT_DIR && -d $GIT_DIR . "/objects" && 
-	-d $GIT_DIR . "/objects/" && -d $GIT_DIR . "/refs") {
-	usage("Git repository not found.");
-}
-
-usage("") if scalar @ARGV != 2;
-
-my ($src,$dst) = @ARGV;
-
-unless (-f $src || -l $src || -d $src) {
-	usage("git rename: bad source '$src'");
-}
-
-if (-e $dst) {
-	usage("git rename: destinations '$dst' already exists");
-}
-
-my (@allfiles,@srcfiles,@dstfiles);
-
-$/ = "\0";
-open(F,"-|","git-ls-files","-z")
-	or die "Failed to open pipe from git-ls-files: " . $!;
-
-@allfiles = map { chomp; $_; } <F>;
-close(F);
-
-my $safesrc = quotemeta($src);
-@srcfiles = grep /^$safesrc/, @allfiles;
-@dstfiles = @srcfiles;
-s#^$safesrc(/|$)#$dst$1# for @dstfiles;
-
-rename($src,$dst)
-	or die "rename failed: $!";
-
-my $rc = system("git-update-index","--add","--",@dstfiles);
-die "git-update-index failed to add new name with code $?\n" if $rc;
-
-$rc = system("git-update-index","--remove","--",@srcfiles);
-die "git-update-index failed to remove old name with code $?\n" if $rc;
-
-
-sub usage($) {
-	my $s = shift;
-	print $s, "\n" if (length $s != 0);
-	print <<EOT;
-$0 <source> <dest>
-source must exist and be either a file, symlink or directory.
-dest must NOT exist.
-
-Renames source to dest, and updates the git cache to reflect the change.
-Use "git commit" to make record the change permanently.
-EOT
-	exit(1);
-}
diff --git a/git-svnimport.perl b/git-svnimport.perl
index cb9afb9..af13fdd 100755
--- a/git-svnimport.perl
+++ b/git-svnimport.perl
@@ -280,7 +280,8 @@
 		$svnpath = "$branch_name/$branch/$path";
 	}
 
-	return $svnpath
+	$svnpath =~ s#/+$##;
+	return $svnpath;
 }
 
 sub get_file($$$) {
@@ -372,6 +373,10 @@
 	my($newrev,$newbranch,$path,$oldpath,$rev,$node_kind,$new,$parents) = @_;
 
 	my($srcbranch,$srcpath) = split_path($rev,$oldpath);
+	unless(defined $srcbranch) {
+		print "Path not found when copying from $oldpath @ $rev\n";
+		return;
+	}
 	my $therev = branch_rev($srcbranch, $rev);
 	my $gitrev = $branches{$srcbranch}{$therev};
 	unless($gitrev) {
diff --git a/http-fetch.c b/http-fetch.c
index f39e748..b8aa965 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -25,7 +25,7 @@
 #define PREV_BUF_SIZE 4096
 #define RANGE_HEADER_SIZE 30
 
-static int got_alternates = 0;
+static int got_alternates = -1;
 static int active_requests = 0;
 static int data_received;
 
@@ -87,9 +87,19 @@
 	int done;
 	CURLcode curl_result;
 	long http_code;
+	void *callback_data;
+	void (*callback_func)(void *data);
 	struct active_request_slot *next;
 };
 
+struct alt_request {
+	char *base;
+	char *url;
+	struct buffer *buffer;
+	struct active_request_slot *slot;
+	int http_specific;
+};
+
 static struct transfer_request *request_queue_head = NULL;
 static struct active_request_slot *active_queue_head = NULL;
 
@@ -237,7 +247,7 @@
 static void process_curl_messages(void);
 static void process_request_queue(void);
 #endif
-static int fetch_alternates(char *base);
+static void fetch_alternates(char *base);
 
 static CURL* get_curl_handle(void)
 {
@@ -324,6 +334,8 @@
 	slot->in_use = 1;
 	slot->done = 0;
 	slot->local = NULL;
+	slot->callback_data = NULL;
+	slot->callback_func = NULL;
 	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
 	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_range_header);
 	curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
@@ -601,6 +613,12 @@
 			} else {
 				fprintf(stderr, "Received DONE message for unknown request!\n");
 			}
+
+			/* Process slot callback if appropriate */
+			if (slot->callback_func != NULL) {
+				slot->callback_func(slot->callback_data);
+			}
+
 			if (request != NULL) {
 				request->curl_result = curl_result;
 				request->http_code = slot->http_code;
@@ -614,6 +632,8 @@
 						request->repo =
 							request->repo->next;
 						start_request(request);
+					} else {
+						finish_request(request);
 					}
 				} else {
 					finish_request(request);
@@ -766,72 +786,51 @@
 	return 0;
 }
 
-static int fetch_alternates(char *base)
+static void process_alternates(void *callback_data)
 {
-	int ret = 0;
-	struct buffer buffer;
-	char *url;
+	struct alt_request *alt_req = (struct alt_request *)callback_data;
+	struct active_request_slot *slot = alt_req->slot;
+	struct alt_base *tail = alt;
+	char *base = alt_req->base;
+	static const char null_byte = '\0';
 	char *data;
 	int i = 0;
-	int http_specific = 1;
-	struct alt_base *tail = alt;
-	static const char null_byte = '\0';
 
-	struct active_request_slot *slot;
+	if (alt_req->http_specific) {
+		if (slot->curl_result != CURLE_OK ||
+		    !alt_req->buffer->posn) {
 
-	if (got_alternates)
-		return 0;
-
-	data = xmalloc(4096);
-	buffer.size = 4096;
-	buffer.posn = 0;
-	buffer.buffer = data;
-
-	if (get_verbosely)
-		fprintf(stderr, "Getting alternates list for %s\n", base);
-	
-	url = xmalloc(strlen(base) + 31);
-	sprintf(url, "%s/objects/info/http-alternates", base);
-
-	slot = get_active_slot();
-	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
-			 fwrite_buffer_dynamic);
-	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-	if (start_active_slot(slot)) {
-		run_active_slot(slot);
-		if (slot->curl_result != CURLE_OK || !buffer.posn) {
-			http_specific = 0;
-
-			sprintf(url, "%s/objects/info/alternates", base);
-
-			slot = get_active_slot();
-			curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-			curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
-					 fwrite_buffer_dynamic);
-			curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+			/* Try reusing the slot to get non-http alternates */
+			alt_req->http_specific = 0;
+			sprintf(alt_req->url, "%s/objects/info/alternates",
+				base);
+			curl_easy_setopt(slot->curl, CURLOPT_URL,
+					 alt_req->url);
+			active_requests++;
+			slot->in_use = 1;
+			slot->done = 0;
 			if (start_active_slot(slot)) {
-				run_active_slot(slot);
-				if (slot->curl_result != CURLE_OK) {
-					free(buffer.buffer);
-					if (slot->http_code == 404)
-						got_alternates = 1;
-					return 0;
-				}
+				return;
+			} else {
+				got_alternates = -1;
+				slot->done = 1;
+				return;
 			}
 		}
-	} else {
-		free(buffer.buffer);
-		return 0;
+	} else if (slot->curl_result != CURLE_OK) {
+		if (slot->http_code != 404) {
+			got_alternates = -1;
+			return;
+		}
 	}
 
-	fwrite_buffer_dynamic(&null_byte, 1, 1, &buffer);
-	buffer.posn--;
-	data = buffer.buffer;
+	fwrite_buffer_dynamic(&null_byte, 1, 1, alt_req->buffer);
+	alt_req->buffer->posn--;
+	data = alt_req->buffer->buffer;
 
-	while (i < buffer.posn) {
+	while (i < alt_req->buffer->posn) {
 		int posn = i;
-		while (posn < buffer.posn && data[posn] != '\n')
+		while (posn < alt_req->buffer->posn && data[posn] != '\n')
 			posn++;
 		if (data[posn] == '\n') {
 			int okay = 0;
@@ -855,7 +854,7 @@
 				// If the server got removed, give up.
 				okay = strchr(base, ':') - base + 3 < 
 					serverlen;
-			} else if (http_specific) {
+			} else if (alt_req->http_specific) {
 				char *colon = strchr(data + i, ':');
 				char *slash = strchr(data + i, '/');
 				if (colon && slash && colon < data + posn &&
@@ -881,15 +880,74 @@
 				while (tail->next != NULL)
 					tail = tail->next;
 				tail->next = newalt;
-				ret++;
 			}
 		}
 		i = posn + 1;
 	}
 
 	got_alternates = 1;
-	free(buffer.buffer);
-	return ret;
+}
+
+static void fetch_alternates(char *base)
+{
+	struct buffer buffer;
+	char *url;
+	char *data;
+	struct active_request_slot *slot;
+	static struct alt_request alt_req;
+	int num_transfers;
+
+	/* If another request has already started fetching alternates,
+	   wait for them to arrive and return to processing this request's
+	   curl message */
+	while (got_alternates == 0) {
+		curl_multi_perform(curlm, &num_transfers);
+		process_curl_messages();
+		process_request_queue();
+	}
+
+	/* Nothing to do if they've already been fetched */
+	if (got_alternates == 1)
+		return;
+
+	/* Start the fetch */
+	got_alternates = 0;
+
+	data = xmalloc(4096);
+	buffer.size = 4096;
+	buffer.posn = 0;
+	buffer.buffer = data;
+
+	if (get_verbosely)
+		fprintf(stderr, "Getting alternates list for %s\n", base);
+	
+	url = xmalloc(strlen(base) + 31);
+	sprintf(url, "%s/objects/info/http-alternates", base);
+
+	/* Use a callback to process the result, since another request
+	   may fail and need to have alternates loaded before continuing */
+	slot = get_active_slot();
+	slot->callback_func = process_alternates;
+	slot->callback_data = &alt_req;
+
+	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
+	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
+			 fwrite_buffer_dynamic);
+	curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+
+	alt_req.base = base;
+	alt_req.url = url;
+	alt_req.buffer = &buffer;
+	alt_req.http_specific = 1;
+	alt_req.slot = slot;
+
+	if (start_active_slot(slot))
+		run_active_slot(slot);
+	else
+		got_alternates = -1;
+
+	free(data);
+	free(url);
 }
 
 static int fetch_indices(struct alt_base *repo)
diff --git a/pack-redundant.c b/pack-redundant.c
index 1f8c577..28b82ee 100644
--- a/pack-redundant.c
+++ b/pack-redundant.c
@@ -593,19 +593,20 @@
 
 	minimize(&min);
 	if (verbose) {
-		fprintf(stderr, "There are %ld packs available in alt-odbs.\n",
-			pack_list_size(altodb_packs));
+		fprintf(stderr, "There are %lu packs available in alt-odbs.\n",
+			(unsigned long)pack_list_size(altodb_packs));
 		fprintf(stderr, "The smallest (bytewise) set of packs is:\n");
 		pl = min;
 		while (pl) {
 			fprintf(stderr, "\t%s\n", pl->pack->pack_name);
 			pl = pl->next;
 		}
-		fprintf(stderr, "containing %ld duplicate objects "
-				"with a total size of %ldkb.\n",
-			get_pack_redundancy(min), pack_set_bytecount(min)/1024);
-		fprintf(stderr, "A total of %ld unique objects were considered.\n",
-			all_objects->size);
+		fprintf(stderr, "containing %lu duplicate objects "
+				"with a total size of %lukb.\n",
+			(unsigned long)get_pack_redundancy(min),
+			(unsigned long)pack_set_bytecount(min)/1024);
+		fprintf(stderr, "A total of %lu unique objects were considered.\n",
+			(unsigned long)all_objects->size);
 		fprintf(stderr, "Redundant packs (with indexes):\n");
 	}
 	pl = red = pack_list_difference(local_packs, min);
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 5f98f64..36f7749 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -24,4 +24,12 @@
     'git branch --help should not have created a bogus branch' \
     'test -f .git/refs/heads/--help'
 
+test_expect_success \
+    'git branch abc should create a branch' \
+    'git-branch abc && test -f .git/refs/heads/abc'
+
+test_expect_success \
+    'git branch a/b/c should create a branch' \
+    'git-branch a/b/c && test -f .git/refs/heads/a/b/c'
+
 test_done
diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh
index 3c4c44c..98f9a1e 100755
--- a/t/t6003-rev-list-topo-order.sh
+++ b/t/t6003-rev-list-topo-order.sh
@@ -25,7 +25,7 @@
 on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0
 on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1
 on_committer_date "1971-08-16 00:00:08" as_author foobar@example.com save_tag b2 unique_commit b2 tree -p b1
-on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b2 tree -p b2
+on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b3 tree -p b2
 on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
 on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2
 on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1
@@ -116,15 +116,15 @@
 EOF
 
 test_output_expect_success 'multiple heads' 'git-rev-list --topo-order a3 b3 c3' <<EOF
-b3
-c3
-c2
-b2
-c1
-b1
 a3
 a2
 a1
+c3
+c2
+c1
+b3
+b2
+b1
 a0
 l2
 l1
@@ -133,26 +133,26 @@
 EOF
 
 test_output_expect_success 'multiple heads, prune at a1' 'git-rev-list --topo-order a3 b3 c3 ^a1' <<EOF
-b3
-c3
-c2
-b2
-c1
-b1
 a3
 a2
+c3
+c2
+c1
+b3
+b2
+b1
 EOF
 
 test_output_expect_success 'multiple heads, prune at l1' 'git-rev-list --topo-order a3 b3 c3 ^l1' <<EOF
-b3
-c3
-c2
-b2
-c1
-b1
 a3
 a2
 a1
+c3
+c2
+c1
+b3
+b2
+b1
 a0
 l2
 EOF
diff --git a/unpack-objects.c b/unpack-objects.c
index 8ae1a1c..8490895 100644
--- a/unpack-objects.c
+++ b/unpack-objects.c
@@ -6,7 +6,7 @@
 #include <sys/time.h>
 
 static int dry_run, quiet;
-static const char unpack_usage[] = "git-unpack-objects [-q] < pack-file";
+static const char unpack_usage[] = "git-unpack-objects [-n] [-q] < pack-file";
 
 /* We always read in 4kB chunks. */
 static unsigned char buffer[4096];
diff --git a/update-ref.c b/update-ref.c
index d79dc52..e6fbddb 100644
--- a/update-ref.c
+++ b/update-ref.c
@@ -19,7 +19,8 @@
 int main(int argc, char **argv)
 {
 	char *hex;
-	const char *refname, *value, *oldval, *path, *lockpath;
+	const char *refname, *value, *oldval, *path;
+	char *lockpath;
 	unsigned char sha1[20], oldsha1[20], currsha1[20];
 	int fd, written;
 
@@ -49,6 +50,8 @@
 	}
 	path = strdup(path);
 	lockpath = mkpath("%s.lock", path);
+	if (safe_create_leading_directories(lockpath) < 0)
+		die("Unable to create all of %s", lockpath);
 
 	fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
 	if (fd < 0)