Commits

Anonymous committed c2f3bf0 Merge

GIT 1.0.0

Signed-off-by: Junio C Hamano <junkio@cox.net>

Comments (0)

Files changed (66)

 git-mktag
 git-name-rev
 git-mv
-git-octopus
 git-pack-redundant
 git-pack-objects
 git-parse-remote

Documentation/diff-options.txt

 	object name of pre- and post-image blob on the "index"
 	line when generating a patch format output.	
 
+--abbrev[=<n>]::
+	Instead of showing the full 40-byte hexadecimal object
+	name in diff-raw format output and diff-tree header
+	lines, show only handful dhexigits prefix.  This is
+	independent of --full-index option above, which controls
+	the diff-patch output format.  Non default number of
+	digits can be specified with --abbrev=<n>.
+
 -B::
 	Break complete rewrite changes into pairs of delete and create.
 

Documentation/everyday.txt

 
 <1> repeat as needed.
 <2> extract patches from your branch for e-mail submission.
-<3> "pull" fetches from "origin" by default and merges.
-<4> look at the changes since last time we checked, only in the
+<3> "pull" fetches from "origin" by default and merges into the
+current branch.
+<4> immediately after pulling, look at the changes done upstream
+since last time we checked, only in the
 area we are interested in.
-<5> fetch from a specific branch from a specific repository and and merge.
+<5> fetch from a specific branch from a specific repository and merge.
 <6> revert the pull.
 <7> garbage collect leftover objects from reverted pull.
 <8> from time to time, obtain official tags from the "origin"
 <8> and bundle topic branches still cooking.
 <9> backport a critical fix.
 <10> create a signed tag.
-<11> make sure I did not accidentally rewound master beyond what I
+<11> make sure I did not accidentally rewind master beyond what I
 already pushed out.  "ko" shorthand points at the repository I have
 at kernel.org, and looks like this:
-$ cat .git/remotes/ko
-URL: kernel.org:/pub/scm/git/git.git
-Pull: master:refs/tags/ko-master
-Pull: maint:refs/tags/ko-maint
-Push: master
-Push: +pu
-Push: maint
+    $ cat .git/remotes/ko
+    URL: kernel.org:/pub/scm/git/git.git
+    Pull: master:refs/tags/ko-master
+    Pull: maint:refs/tags/ko-maint
+    Push: master
+    Push: +pu
+    Push: maint
+In the output from "git show-branch", "master" should have
+everything "ko-master" has.
 <12> push out the bleeding edge.
 <13> push the tag out, too.
 ------------
   * gitlink:git-shell[1] can be used as a 'restricted login shell'
     for shared central repository users.
 
-  * link:howto/update-hook-example.txt[update hook howto] has a
-    good example of managing a shared central repository.
+link:howto/update-hook-example.txt[update hook howto] has a good
+example of managing a shared central repository.
 
 
 Examples
 david is the release manager and is the only person who can
 create and push version tags.
 ------------
+
+HTTP server to support dumb protocol transfer.::
++
+------------
+dev$ git update-server-info <1>
+dev$ ftp user@isp.example.com <2>
+ftp> cp -r .git /home/user/myproject.git
+
+<1> make sure your info/refs and objects/info/packs are up-to-date
+<2> upload to public HTTP server hosted by your ISP.
+------------

Documentation/git-archimport.txt

 
 SYNOPSIS
 --------
-`git-archimport` [ -h ] [ -v ] [ -T ] [ -t tempdir ] 
+`git-archimport` [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
+                 [ -D depth ] [ -t tempdir ] 
                  <archive/branch> [ <archive/branch> ]
 
 DESCRIPTION
 	Many tags. Will create a tag for every commit, reflecting the commit 
 	name in the Arch repository.
 
+-f::
+	Use the fast patchset import strategy.  This can be significantly
+	faster for large trees, but cannot handle directory renames or
+	permissions changes.  The default strategy is slow and safe.
+
+-o::
+	Use this for compatibility with old-style branch names used by
+	earlier versions of git-archimport.  Old-style branch names
+	were category--branch, whereas new-style branch names are
+	archive,category--branch--version.
+
+-D <depth>::
+	Follow merge ancestry and attempt to import trees that have been
+	merged from.  Specify a depth greater than 1 if patch logs have been
+	pruned.
+
+-a::
+	Attempt to auto-register archives at http://mirrors.sourcecontrol.net
+	This is particularly useful with the -D option.
+
 -t <tmpdir>::
 	Override the default tempdir.
 

Documentation/git-check-ref-format.txt

 
 . It cannot have ASCII control character (i.e. bytes whose
   values are lower than \040, or \177 `DEL`), space, tilde `~`,
-  caret `{caret}`, or colon `:` anywhere;
+  caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
+  or open bracket `[` anywhere;
 
 . It cannot end with a slash `/`.
 
 These rules makes it easy for shell script based tools to parse
-refnames, and also avoids ambiguities in certain refname
-expressions (see gitlink:git-rev-parse[1]).  Namely:
+refnames, pathname expansion by the shell when a refname is used
+unquoted (by mistake), and also avoids ambiguities in certain
+refname expressions (see gitlink:git-rev-parse[1]).  Namely:
 
 . double-dot `..` are often used as in `ref1..ref2`, and in some
   context this notation means `{caret}ref1 ref2` (i.e. not in

Documentation/git-clone-pack.txt

 	The heads to update.  This is relative to $GIT_DIR
 	(e.g. "HEAD", "refs/heads/master").  When unspecified,
 	all heads are updated to match the remote repository.
-
++
+Usually all the refs from existing repository are stored
+under the same name in the new repository.  Giving explicit
+<head> arguments instead writes the object names and refs to
+the standard output, just like get-fetch-pack does.
 
 Author
 ------

Documentation/git-commit.txt

 	Update specified paths in the index file before committing.
 
 
+If you make a commit and then found a mistake immediately after
+that, you can recover from it with gitlink:git-reset[1].
+
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org> and

Documentation/git-fetch-pack.txt

 
 SYNOPSIS
 --------
-git-fetch-pack [-q] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
+git-fetch-pack [-q] [-k] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
 
 DESCRIPTION
 -----------
 	Pass '-q' flag to 'git-unpack-objects'; this makes the
 	cloning process less verbose.
 
+-k::
+	Do not invoke 'git-unpack-objects' on received data, but
+	create a single packfile out of it instead, and store it
+	in the object database.
+
 --exec=<git-upload-pack>::
 	Use this to specify the path to 'git-upload-pack' on the
 	remote side, if is not found on your $PATH.

Documentation/git-merge.txt

 include::merge-strategies.txt[]
 
 
+If you tried a merge which resulted in a complex conflicts and
+would want to start over, you can recover with
+gitlink:git-reset[1].
+
+
 HOW MERGE WORKS
 ---------------
 

Documentation/git-octopus.txt

-git-octopus(1)
-==============
-
-NAME
-----
-git-octopus - Merge more than two commits.
-
-
-SYNOPSIS
---------
-'git-octopus'
-
-DESCRIPTION
------------
-After running 'git fetch', $GIT_DIR/FETCH_HEAD contains the
-following information, one line per remote ref:
-
-------------------------------------------------
-<object name>	<ref name> from <repository>
-------------------------------------------------
-
-Using this information, create and commit an Octopus merge on
-top of the current HEAD.
-
-
-Author
-------
-Written by Junio C Hamano <junkio@cox.net>
-
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
-

Documentation/git-pull.txt

 local `master` branch.
 
 
+If you tried a pull which resulted in a complex conflicts and
+would want to start over, you can recover with
+gitlink:git-reset[1].
+
+
 SEE ALSO
 --------
 gitlink:git-fetch[1], gitlink:git-merge[1]

Documentation/git-reset.txt

 changes still in the working tree.
 ------------
 
+Undo a merge or pull::
++
+------------
+$ git pull <1>
+Trying really trivial in-index merge...
+fatal: Merge requires file-level merging
+Nope.
+...
+Auto-merging nitfol
+CONFLICT (content): Merge conflict in nitfol
+Automatic merge failed/prevented; fix up by hand
+$ git reset --hard <2>
+
+<1> try to update from the upstream resulted in a lot of
+conflicts; you were not ready to spend a lot of time merging
+right now, so you decide to do that later.
+<2> "pull" has not made merge commit, so "git reset --hard"
+which is a synonym for "git reset --hard HEAD" clears the mess
+from the index file and the working tree.
+
+$ git pull . topic/branch <3>
+Updating from 41223... to 13134...
+Fast forward
+$ git reset --hard ORIG_HEAD <4>
+
+<3> merge a topic branch into the current branch, which resulted
+in a fast forward.
+<4> but you decided that the topic branch is not ready for public
+consumption yet.  "pull" or "merge" always leaves the original
+tip of the current branch in ORIG_HEAD, so resetting hard to it
+brings your index file and the working tree back to that state,
+and resets the tip of the branch to that commit.
+------------
 
 Author
 ------

Documentation/git-update-server-info.txt

 
 DESCRIPTION
 -----------
-A dumb server that does not do on-the-fly pack generations can
+A dumb server that does not do on-the-fly pack generations must
 have some auxiliary information files in $GIT_DIR/info and
 $GIT_OBJECT_DIRECTORY/info directories to help clients discover
-what references and packs the server has and make optimized
-pull decisions.  This command generates such auxiliary files.
+what references and packs the server has.  This command
+generates such auxiliary files.
 
 
 OPTIONS

Documentation/git.txt

 gitlink:git-mv[1]::
 	Move or rename a file, a directory, or a symlink.
 
-gitlink:git-octopus[1]::
-	Merge more than two commits.
-
 gitlink:git-pull[1]::
 	Fetch from and merge with a remote repository.
 

Documentation/hooks.txt

 implement access control which is finer grained than the one
 based on filesystem group.
 
+The standard output of this hook is sent to /dev/null; if you
+want to report something to the git-send-pack on the other end,
+you can redirect your output to your stderr.
+
 post-update
 -----------
 
 The default post-update hook, when enabled, runs
 `git-update-server-info` to keep the information used by dumb
 transport up-to-date.
+
+The standard output of this hook is sent to /dev/null; if you
+want to report something to the git-send-pack on the other end,
+you can redirect your output to your stderr.

Documentation/howto/rebuild-from-update-hook.txt

 are built from Documentation/ directory of the git.git project
 and needed to be kept up-to-date.  The www.kernel.org/ servers
 are mirrored and I was told that the origin of the mirror is on
-the machine master.kernel.org, on which I was given an account
+the machine $some.kernel.org, on which I was given an account
 when I took over git maintainership from Linus.
 
 The directories relevant to this how-to are these two:
     EOF
     $ chmod +x /pub/scm/git/git.git/hooks/post-update
 
-There are three things worth mentioning:
+There are four things worth mentioning:
 
  - The update-hook is run after the repository accepts a "git
    push", under my user privilege.  It is given the full names
    pull" it does into $HOME/doc-git/docgen/ repository would not
    work correctly.
 
+ - The stdout of update hook script is not connected to git
+   push; I run the heavy part of the command inside "at", to
+   receive the execution report via e-mail.
+
  - This is still crude and does not protect against simultaneous
    make invocations stomping on each other.  I would need to add
    some locking mechanism for this.

Documentation/howto/using-topic-branches.txt

 
 First create your work tree by cloning Linus's public tree:
 
- $ git clone \
- master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
+ $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
 
 Change directory into the cloned tree you just created
 
 branch into a local branch named "linus":
 
  $ cat > .git/remotes/linus
- URL: master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+ URL: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
  Pull: master:linus
  ^D
 

Documentation/tutorial.txt

 [NOTE]
 And those "too deep" descriptions are often marked as Note.
 
+[NOTE]
+If you are already familiar with another version control system,
+like CVS, you may want to take a look at
+link:everyday.html[Everyday GIT in 20 commands or so] first
+before reading this.
+
 
 Creating a git repository
 -------------------------
 HTTP(S)::
 	`http://remote.machine/path/to/repo.git/`
 +
-HTTP and HTTPS transport are used only for downloading.  They
-first obtain the topmost commit object name from the remote site
-by looking at `repo.git/info/refs` file, tries to obtain the
+Downloader from http and https URL
+first obtains the topmost commit object name from the remote site
+by looking at the specified refname under `repo.git/refs/` directory,
+and then tries to obtain the
 commit object by downloading from `repo.git/objects/xx/xxx\...`
 using the object name of that commit object.  Then it reads the
 commit object to find out its parent commits and the associate
 The 'commit walkers' are sometimes also called 'dumb
 transports', because they do not require any git aware smart
 server like git Native transport does.  Any stock HTTP server
-would suffice.
+that does not even support directory index would suffice.  But
+you must prepare your repository with `git-update-server-info`
+to help dumb transport downloaders.
 +
 There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload`
 programs, which are 'commit walkers'; they outlived their
 2. Prepare a public repository accessible to others.
 +
 If other people are pulling from your repository over dumb
-transport protocols, you need to keep this repository 'dumb
-transport friendly'.  After `git init-db`,
+transport protocols (HTTP), you need to keep this repository
+'dumb transport friendly'.  After `git init-db`,
 `$GIT_DIR/hooks/post-update` copied from the standard templates
 would contain a call to `git-update-server-info` but the
 `post-update` hook itself is disabled by default -- enable it
-with `chmod +x post-update`.
+with `chmod +x post-update`.  This makes sure `git-update-server-info`
+keeps the necessary files up-to-date.
 
 3. Push into the public repository from your primary
    repository.
 For this, set up a public repository on a machine that is
 reachable via SSH by people with "commit privileges".  Put the
 committers in the same user group and make the repository
-writable by that group.
+writable by that group.  Make sure their umasks are set up to
+allow group members to write into directories other members
+have created.
 
 You, as an individual committer, then:
 
 # 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.9n
+GIT_VERSION = 1.0.0
 
 # CFLAGS and LDFLAGS are for the users to override from the command line.
 
 	git-cherry.sh git-clone.sh git-commit.sh \
 	git-count-objects.sh git-diff.sh git-fetch.sh \
 	git-format-patch.sh git-log.sh git-ls-remote.sh \
-	git-merge-one-file.sh git-octopus.sh git-parse-remote.sh \
+	git-merge-one-file.sh git-parse-remote.sh \
 	git-prune.sh git-pull.sh git-push.sh git-rebase.sh \
 	git-repack.sh git-request-pull.sh git-reset.sh \
 	git-resolve.sh git-revert.sh git-sh-setup.sh git-status.sh \
 	quote.o read-cache.o refs.o run-command.o \
 	server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
 	tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
+	fetch-clone.o \
 	$(DIFF_OBJS)
 
 LIBS = $(LIB_FILE)
 	rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(LIB_FILE)
 	rm -f $(PROGRAMS) $(SIMPLE_PROGRAMS) git$X
 	rm -f $(filter-out gitk,$(SCRIPTS))
-	rm -f *.spec *.pyc *.pyo
+	rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo
 	rm -rf $(GIT_TARNAME)
 	rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
 	rm -f git-core_$(GIT_VERSION)-*.dsc
 	$(MAKE) -C Documentation/ clean
 	$(MAKE) -C templates clean
 	$(MAKE) -C t/ clean
+
 			buffer = xrealloc(buffer, alloc);
 			nr = alloc - size;
 		}
-		nr = read(fd, buffer + size, nr);
+		nr = xread(fd, buffer + size, nr);
 		if (!nr)
 			break;
-		if (nr < 0) {
-			if (errno == EAGAIN)
-				continue;
+		if (nr < 0)
 			die("git-apply: read returned %s", strerror(errno));
-		}
 		size += nr;
 	}
 	*sizep = size;
 			return error("unable to open %s", path);
 		got = 0;
 		for (;;) {
-			int ret = read(fd, buf + got, size - got);
-			if (ret < 0) {
-				if (errno == EAGAIN)
-					continue;
-				break;
-			}
-			if (!ret)
+			int ret = xread(fd, buf + got, size - got);
+			if (ret <= 0)
 				break;
 			got += ret;
 		}
 	if (fd < 0)
 		return -1;
 	while (size) {
-		int written = write(fd, buf, size);
-		if (written < 0) {
-			if (errno == EINTR || errno == EAGAIN)
-				continue;
+		int written = xwrite(fd, buf, size);
+		if (written < 0)
 			die("writing file %s: %s", path, strerror(errno));
-		}
 		if (!written)
 			die("out of space writing file %s", path);
 		buf += written;
 extern char git_commit_encoding[MAX_ENCODING_LENGTH];
 
 extern int copy_fd(int ifd, int ofd);
+
+/* Finish off pack transfer receiving end */
+extern int receive_unpack_pack(int fd[2], const char *me, int quiet);
+extern int receive_keep_pack(int fd[2], const char *me);
+
 #endif /* CACHE_H */
 		die("git-cat-file %s: bad file", argv[2]);
 
 	while (size > 0) {
-		long ret = write(1, buf, size);
+		long ret = xwrite(1, buf, size);
 		if (ret < 0) {
-			if (errno == EAGAIN)
-				continue;
 			/* Ignore epipe */
 			if (errno == EPIPE)
 				break;
 #include "cache.h"
 #include "refs.h"
 #include "pkt-line.h"
-#include <sys/wait.h>
 
 static const char clone_pack_usage[] =
 "git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
 	free(head_path);
 }
 
-static int finish_pack(const char *pack_tmp_name)
-{
-	int pipe_fd[2];
-	pid_t pid;
-	char idx[PATH_MAX];
-	char final[PATH_MAX];
-	char hash[41];
-	unsigned char sha1[20];
-	char *cp;
-	int err = 0;
-
-	if (pipe(pipe_fd) < 0)
-		die("git-clone-pack: unable to set up pipe");
-
-	strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */
-	cp = strrchr(idx, '/');
-	memcpy(cp, "/pidx", 5);
-
-	pid = fork();
-	if (pid < 0)
-		die("git-clone-pack: unable to fork off git-index-pack");
-	if (!pid) {
-		close(0);
-		dup2(pipe_fd[1], 1);
-		close(pipe_fd[0]);
-		close(pipe_fd[1]);
-		execlp("git-index-pack","git-index-pack",
-		       "-o", idx, pack_tmp_name, NULL);
-		error("cannot exec git-index-pack <%s> <%s>",
-		      idx, pack_tmp_name);
-		exit(1);
-	}
-	close(pipe_fd[1]);
-	if (read(pipe_fd[0], hash, 40) != 40) {
-		error("git-clone-pack: unable to read from git-index-pack");
-		err = 1;
-	}
-	close(pipe_fd[0]);
-
-	for (;;) {
-		int status, code;
-		int retval = waitpid(pid, &status, 0);
-
-		if (retval < 0) {
-			if (errno == EINTR)
-				continue;
-			error("waitpid failed (%s)", strerror(retval));
-			goto error_die;
-		}
-		if (WIFSIGNALED(status)) {
-			int sig = WTERMSIG(status);
-			error("git-index-pack died of signal %d", sig);
-			goto error_die;
-		}
-		if (!WIFEXITED(status)) {
-			error("git-index-pack died of unnatural causes %d",
-			      status);
-			goto error_die;
-		}
-		code = WEXITSTATUS(status);
-		if (code) {
-			error("git-index-pack died with error code %d", code);
-			goto error_die;
-		}
-		if (err)
-			goto error_die;
-		break;
-	}
-	hash[40] = 0;
-	if (get_sha1_hex(hash, sha1)) {
-		error("git-index-pack reported nonsense '%s'", hash);
-		goto error_die;
-	}
-	/* Now we have pack in pack_tmp_name[], and
-	 * idx in idx[]; rename them to their final names.
-	 */
-	snprintf(final, sizeof(final),
-		 "%s/pack/pack-%s.pack", get_object_directory(), hash);
-	move_temp_to_file(pack_tmp_name, final);
-	chmod(final, 0444);
-	snprintf(final, sizeof(final),
-		 "%s/pack/pack-%s.idx", get_object_directory(), hash);
-	move_temp_to_file(idx, final);
-	chmod(final, 0444);
-	return 0;
-
- error_die:
-	unlink(idx);
-	unlink(pack_tmp_name);
-	exit(1);
-}
-
-static int clone_without_unpack(int fd[2])
-{
-	char tmpfile[PATH_MAX];
-	int ofd, ifd;
-
-	ifd = fd[0];
-	snprintf(tmpfile, sizeof(tmpfile),
-		 "%s/pack/tmp-XXXXXX", get_object_directory());
-	ofd = mkstemp(tmpfile);
-	if (ofd < 0)
-		return error("unable to create temporary file %s", tmpfile);
-
-	while (1) {
-		char buf[8192];
-		ssize_t sz, wsz, pos;
-		sz = read(ifd, buf, sizeof(buf));
-		if (sz == 0)
-			break;
-		if (sz < 0) {
-			error("error reading pack (%s)", strerror(errno));
-			close(ofd);
-			unlink(tmpfile);
-			return -1;
-		}
-		pos = 0;
-		while (pos < sz) {
-			wsz = write(ofd, buf + pos, sz - pos);
-			if (wsz < 0) {
-				error("error writing pack (%s)",
-				      strerror(errno));
-				close(ofd);
-				unlink(tmpfile);
-				return -1;
-			}
-			pos += wsz;
-		}
-	}
-	close(ofd);
-	return finish_pack(tmpfile);
-}
-
 static int clone_pack(int fd[2], int nr_match, char **match)
 {
 	struct ref *refs;
 	}
 	clone_handshake(fd, refs);
 
-	status = clone_without_unpack(fd);
-
-	if (!status)
-		write_refs(refs);
+	status = receive_keep_pack(fd, "git-clone-pack");
+
+	if (!status) {
+		if (nr_match == 0)
+			write_refs(refs);
+		else
+			while (refs) {
+				printf("%s %s\n",
+				       sha1_to_hex(refs->old_sha1),
+				       refs->name);
+				refs = refs->next;
+			}
+	}
 	return status;
 }
 
 				exec = arg + 7;
 				continue;
 			}
-			if (!strcmp("--keep", arg))
-				continue;
 			usage(clone_pack_usage);
 		}
 		dest = arg;

cmd-rename.sh

-#!/bin/sh
-#
-# If you installed git by hand previously, you may find this
-# script useful to remove the symbolic links that we shipped
-# for backward compatibility.
-#
-# Running this script with the previous installation directory
-# like this:
-#
-# $ cmd-rename.sh /usr/local/bin/
-#
-# would clean them.
-
-d="$1"
-test -d "$d" || exit
-while read old new
-do
-	rm -f "$d/$old"
-done <<\EOF
-git-add-script	git-add
-git-archimport-script	git-archimport
-git-bisect-script	git-bisect
-git-branch-script	git-branch
-git-checkout-script	git-checkout
-git-cherry-pick-script	git-cherry-pick
-git-clone-script	git-clone
-git-commit-script	git-commit
-git-count-objects-script	git-count-objects
-git-cvsimport-script	git-cvsimport
-git-diff-script	git-diff
-git-send-email-script	git-send-email
-git-fetch-script	git-fetch
-git-format-patch-script	git-format-patch
-git-log-script	git-log
-git-ls-remote-script	git-ls-remote
-git-merge-one-file-script	git-merge-one-file
-git-octopus-script	git-octopus
-git-parse-remote-script	git-parse-remote
-git-prune-script	git-prune
-git-pull-script	git-pull
-git-push-script	git-push
-git-rebase-script	git-rebase
-git-relink-script	git-relink
-git-rename-script	git-rename
-git-repack-script	git-repack
-git-request-pull-script	git-request-pull
-git-reset-script	git-reset
-git-resolve-script	git-resolve
-git-revert-script	git-revert
-git-sh-setup-script	git-sh-setup
-git-status-script	git-status
-git-tag-script	git-tag
-git-verify-tag-script	git-verify-tag
-git-http-pull	git-http-fetch
-git-local-pull	git-local-fetch
-git-checkout-cache	git-checkout-index
-git-diff-cache	git-diff-index
-git-merge-cache	git-merge-index
-git-update-cache	git-update-index
-git-convert-cache	git-convert-objects
-git-fsck-cache	git-fsck-objects
-EOF
 		int len;
 		char buffer[8192];
 		char *buf = buffer;
-		len = read(ifd, buffer, sizeof(buffer));
+		len = xread(ifd, buffer, sizeof(buffer));
 		if (!len)
 			break;
 		if (len < 0) {
 			int read_error;
-			if (errno == EAGAIN)
-				continue;
 			read_error = errno;
 			close(ifd);
 			return error("copy-fd: read returned %s",
 				     strerror(read_error));
 		}
-		while (1) {
-			int written = write(ofd, buf, len);
+		while (len) {
+			int written = xwrite(ofd, buf, len);
 			if (written > 0) {
 				buf += written;
 				len -= written;
-				if (!len)
-					break;
 			}
-			if (!written)
+			else if (!written)
 				return error("copy-fd: write returned 0");
-			if (errno == EAGAIN || errno == EINTR)
-				continue;
-			return error("copy-fd: write returned %s",
-				     strerror(errno));
+			else
+				return error("copy-fd: write returned %s",
+					     strerror(errno));
 		}
 	}
 	close(ifd);
 	void *buf = f->buffer;
 
 	for (;;) {
-		int ret = write(f->fd, buf, count);
+		int ret = xwrite(f->fd, buf, count);
 		if (ret > 0) {
 			buf += ret;
 			count -= ret;
 		}
 		if (!ret)
 			die("sha1 file '%s' write error. Out of diskspace", f->name);
-		if (errno == EAGAIN || errno == EINTR)
-			continue;
 		die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
 	}
 }
+git-core (1.0.0-0) unstable; urgency=low
+
+  * GIT 1.0.0
+
+ -- Junio C Hamano <junkio@cox.net>  Wed, 21 Dec 2005 00:01:00 -0800
+
 git-core (0.99.9n-0) unstable; urgency=low
 
   * GIT 0.99.9n aka 1.0rc6
 } chanode_t;
 
 typedef struct s_chastore {
-	chanode_t *head, *tail;
 	int isize, nsize;
 	chanode_t *ancur;
-	chanode_t *sncur;
-	int scurr;
 } chastore_t;
 
 static void cha_init(chastore_t *cha, int isize, int icount)
 {
-	cha->head = cha->tail = NULL;
 	cha->isize = isize;
 	cha->nsize = icount * isize;
-	cha->ancur = cha->sncur = NULL;
-	cha->scurr = 0;
+	cha->ancur = NULL;
 }
 
 static void *cha_alloc(chastore_t *cha)
 		if (!ancur)
 			return NULL;
 		ancur->icurr = 0;
-		ancur->next = NULL;
-		if (cha->tail)
-			cha->tail->next = ancur;
-		if (!cha->head)
-			cha->head = ancur;
-		cha->tail = ancur;
+		ancur->next = cha->ancur;
 		cha->ancur = ancur;
 	}
 
 
 static void cha_free(chastore_t *cha)
 {
-	chanode_t *cur = cha->head;
+	chanode_t *cur = cha->ancur;
 	while (cur) {
 		chanode_t *tmp = cur;
 		cur = cur->next;
 } bdrecord_t;
 
 typedef struct s_bdfile {
-	const unsigned char *data, *top;
 	chastore_t cha;
 	unsigned int fphbits;
 	bdrecord_t **fphash;
 {
 	unsigned int fphbits;
 	int i, hsize;
-	const unsigned char *base, *data, *top;
+	const unsigned char *data, *top;
 	bdrecord_t *brec;
 	bdrecord_t **fphash;
 
 		fphash[i] = NULL;
 	cha_init(&bdf->cha, sizeof(bdrecord_t), hsize / 4 + 1);
 
-	bdf->data = data = base = buf;
-	bdf->top = top = buf + bufsize;
-	data += (bufsize / BLK_SIZE) * BLK_SIZE;
+	top = buf + bufsize;
+	data = buf + (bufsize / BLK_SIZE) * BLK_SIZE;
 	if (data == top)
 		data -= BLK_SIZE;
 
-	for ( ; data >= base; data -= BLK_SIZE) {
+	for ( ; data >= buf; data -= BLK_SIZE) {
 		brec = cha_alloc(&bdf->cha);
 		if (!brec) {
 			cha_free(&bdf->cha);
 {
 	int i, outpos, outsize, inscnt, csize, msize, moff;
 	unsigned int fp;
-	const unsigned char *data, *top, *ptr1, *ptr2;
+	const unsigned char *ref_data, *ref_top, *data, *top, *ptr1, *ptr2;
 	unsigned char *out, *orig;
 	bdrecord_t *brec;
 	bdfile_t bdf;
 		return NULL;
 	}
 
+	ref_data = from_buf;
+	ref_top = from_buf + from_size;
 	data = to_buf;
 	top = to_buf + to_size;
 
 		i = HASH(fp, bdf.fphbits);
 		for (brec = bdf.fphash[i]; brec; brec = brec->next) {
 			if (brec->fp == fp) {
-				csize = bdf.top - brec->ptr;
+				csize = ref_top - brec->ptr;
 				if (csize > top - data)
 					csize = top - data;
 				for (ptr1 = brec->ptr, ptr2 = data; 
 
 				csize = ptr1 - brec->ptr;
 				if (csize > msize) {
-					moff = brec->ptr - bdf.data;
+					moff = brec->ptr - ref_data;
 					msize = csize;
 					if (msize >= 0x10000) {
 						msize = 0x10000;
 
 static struct diff_options diff_options;
 
-static void call_diff_setup_done(void)
-{
-	diff_setup_done(&diff_options);
-}
-
 static int call_diff_flush(void)
 {
 	diffcore_std(&diff_options);
 {
 	int ret;
 
-	call_diff_setup_done();
 	ret = diff_tree_sha1(old, new, base, &diff_options);
 	call_diff_flush();
 	return ret;
 	void *tree;
 	struct tree_desc empty, real;
 
-	call_diff_setup_done();
 	tree = read_object_with_reference(new, "tree", &real.size, NULL);
 	if (!tree)
 		die("unable to read root tree (%s)", sha1_to_hex(new));
 	return retval;
 }
 
-static const char *generate_header(const char *commit, const char *parent, const char *msg)
+static const char *generate_header(const unsigned char *commit_sha1,
+				   const unsigned char *parent_sha1,
+				   const char *msg)
 {
 	static char this_header[16384];
 	int offset;
 	unsigned long len;
+	int abbrev = diff_options.abbrev;
 
 	if (!verbose_header)
-		return commit;
+		return sha1_to_hex(commit_sha1);
 
 	len = strlen(msg);
-	offset = sprintf(this_header, "%s%s (from %s)\n", header_prefix, commit, parent);
-	offset += pretty_print_commit(commit_format, msg, len, this_header + offset, sizeof(this_header) - offset);
+
+	offset = sprintf(this_header, "%s%s ",
+			 header_prefix,
+			 diff_unique_abbrev(commit_sha1, abbrev));
+	offset += sprintf(this_header + offset, "(from %s)\n",
+			 parent_sha1 ?
+			 diff_unique_abbrev(parent_sha1, abbrev) : "root");
+	offset += pretty_print_commit(commit_format, msg, len,
+				      this_header + offset,
+				      sizeof(this_header) - offset);
 	return this_header;
 }
 
 	
 	/* Root commit? */
 	if (show_root_diff && !commit->parents) {
-		header = generate_header(name, "root", commit->buffer);
+		header = generate_header(sha1, NULL, commit->buffer);
 		diff_root_tree(commit_sha1, "");
 	}
 
 	/* More than one parent? */
 	if (ignore_merges && commit->parents && commit->parents->next)
-			return 0;
+		return 0;
 
 	for (parents = commit->parents; parents; parents = parents->next) {
 		struct commit *parent = parents->item;
-		header = generate_header(name,
-					 sha1_to_hex(parent->object.sha1),
+		header = generate_header(sha1,
+					 parent->object.sha1,
 					 commit->buffer);
 		diff_tree_sha1_top(parent->object.sha1, commit_sha1, "");
 		if (!header && verbose_header) {
 	int len = strlen(line);
 	unsigned char commit[20], parent[20];
 	static char this_header[1000];
+	int abbrev = diff_options.abbrev;
 
 	if (!len || line[len-1] != '\n')
 		return -1;
 	if (isspace(line[40]) && !get_sha1_hex(line+41, parent)) {
 		line[40] = 0;
 		line[81] = 0;
-		sprintf(this_header, "%s (from %s)\n", line, line+41);
+		sprintf(this_header, "%s (from %s)\n",
+			diff_unique_abbrev(commit, abbrev),
+			diff_unique_abbrev(parent, abbrev));
 		header = this_header;
 		return diff_tree_sha1_top(parent, commit, "");
 	}
 		diff_options.recursive = 1;
 
 	diff_tree_setup_paths(get_pathspec(prefix, argv));
+	diff_setup_done(&diff_options);
 
 	switch (nr_sha1) {
 	case 0:
 
 	if (memcmp(one->sha1, two->sha1, 20)) {
 		char one_sha1[41];
-		const char *index_fmt = o->full_index ? "index %s..%s" : "index %.7s..%.7s";
+		int abbrev = o->full_index ? 40 : DIFF_DEFAULT_INDEX_ABBREV;
 		memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
 
 		len += snprintf(msg + len, sizeof(msg) - len,
-				index_fmt, one_sha1, sha1_to_hex(two->sha1));
+				"index %.*s..%.*s",
+				abbrev, one_sha1, abbrev,
+				sha1_to_hex(two->sha1));
 		if (one->mode == two->mode)
 			len += snprintf(msg + len, sizeof(msg) - len,
 					" %06o", one->mode);
 	}
 	if (options->setup & DIFF_SETUP_USE_SIZE_CACHE)
 		use_size_cache = 1;
+	if (options->abbrev <= 0 || 40 < options->abbrev)
+		options->abbrev = 40; /* full */
 
 	return 0;
 }
 	}
 	else if (!strcmp(arg, "--find-copies-harder"))
 		options->find_copies_harder = 1;
+	else if (!strcmp(arg, "--abbrev"))
+		options->abbrev = DIFF_DEFAULT_ABBREV;
+	else if (!strncmp(arg, "--abbrev=", 9))
+		options->abbrev = strtoul(arg + 9, NULL, 10);
 	else
 		return 0;
 	return 1;
 	free(p);
 }
 
+/* This is different from find_unique_abbrev() in that
+ * it needs to deal with 0{40} SHA1.
+ */
+const char *diff_unique_abbrev(const unsigned char *sha1, int len)
+{
+	int abblen;
+	const char *abbrev;
+	if (len == 40)
+		return sha1_to_hex(sha1);
+
+	abbrev = find_unique_abbrev(sha1, len);
+	if (!abbrev) {
+		if (!memcmp(sha1, null_sha1, 20)) {
+			char *buf = sha1_to_hex(null_sha1);
+			if (len < 37)
+				strcpy(buf + len, "...");
+			return buf;
+		}
+		else 
+			return sha1_to_hex(sha1);
+	}
+	abblen = strlen(abbrev);
+	if (abblen < 37) {
+		static char hex[41];
+		if (len < abblen && abblen <= len + 2)
+			sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
+		else
+			sprintf(hex, "%s...", abbrev);
+		return hex;
+	}
+	return sha1_to_hex(sha1);
+}
+
 static void diff_flush_raw(struct diff_filepair *p,
 			   int line_termination,
 			   int inter_name_termination,
-			   int output_format)
+			   struct diff_options *options)
 {
 	int two_paths;
 	char status[10];
+	int abbrev = options->abbrev;
 	const char *path_one, *path_two;
+	int output_format = options->output_format;
 
 	path_one = p->one->path;
 	path_two = p->two->path;
 	}
 	if (output_format != DIFF_FORMAT_NAME_STATUS) {
 		printf(":%06o %06o %s ",
-		       p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1));
-		printf("%s ", sha1_to_hex(p->two->sha1));
+		       p->one->mode, p->two->mode,
+		       diff_unique_abbrev(p->one->sha1, abbrev));
+		printf("%s ",
+		       diff_unique_abbrev(p->two->sha1, abbrev));
 	}
 	printf("%s%c%s", status, inter_name_termination, path_one);
 	if (two_paths)
 		case DIFF_FORMAT_NAME_STATUS:
 			diff_flush_raw(p, line_termination,
 				       inter_name_termination,
-				       diff_output_format);
+				       options);
 			break;
 		case DIFF_FORMAT_NAME:
 			diff_flush_name(p,
 	int reverse_diff;
 	int rename_limit;
 	int setup;
+	int abbrev;
 
 	change_fn_t change;
 	add_remove_fn_t add_remove;
 
 #define DIFF_PICKAXE_ALL	1
 
+#define DIFF_DEFAULT_INDEX_ABBREV	7 /* hex digits */
+#define DIFF_DEFAULT_ABBREV	7 /* hex digits */
+
 extern void diffcore_std(struct diff_options *);
 
 extern void diffcore_std_no_resolve(struct diff_options *);
 "  -u            synonym for -p.\n" \
 "  --name-only   show only names of changed files.\n" \
 "  --name-status show names and status of changed files.\n" \
-"  --full-index  show full object name on index ines.\n" \
+"  --full-index  show full object name on index lines.\n" \
+"  --abbrev=<n>  abbreviate object names in diff-tree header and diff-raw.\n" \
 "  -R            swap input file pairs.\n" \
 "  -B            detect complete rewrites.\n" \
 "  -M            detect renames.\n" \
 #define DIFF_STATUS_FILTER_AON		'*'
 #define DIFF_STATUS_FILTER_BROKEN	'B'
 
+extern const char *diff_unique_abbrev(const unsigned char *, int);
+
 #endif /* DIFF_H */
+#include "cache.h"
+#include <sys/wait.h>
+
+static int finish_pack(const char *pack_tmp_name, const char *me)
+{
+	int pipe_fd[2];
+	pid_t pid;
+	char idx[PATH_MAX];
+	char final[PATH_MAX];
+	char hash[41];
+	unsigned char sha1[20];
+	char *cp;
+	int err = 0;
+
+	if (pipe(pipe_fd) < 0)
+		die("%s: unable to set up pipe", me);
+
+	strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */
+	cp = strrchr(idx, '/');
+	memcpy(cp, "/pidx", 5);
+
+	pid = fork();
+	if (pid < 0)
+		die("git-clone-pack: unable to fork off git-index-pack");
+	if (!pid) {
+		close(0);
+		dup2(pipe_fd[1], 1);
+		close(pipe_fd[0]);
+		close(pipe_fd[1]);
+		execlp("git-index-pack","git-index-pack",
+		       "-o", idx, pack_tmp_name, NULL);
+		error("cannot exec git-index-pack <%s> <%s>",
+		      idx, pack_tmp_name);
+		exit(1);
+	}
+	close(pipe_fd[1]);
+	if (read(pipe_fd[0], hash, 40) != 40) {
+		error("%s: unable to read from git-index-pack", me);
+		err = 1;
+	}
+	close(pipe_fd[0]);
+
+	for (;;) {
+		int status, code;
+		int retval = waitpid(pid, &status, 0);
+
+		if (retval < 0) {
+			if (errno == EINTR)
+				continue;
+			error("waitpid failed (%s)", strerror(retval));
+			goto error_die;
+		}
+		if (WIFSIGNALED(status)) {
+			int sig = WTERMSIG(status);
+			error("git-index-pack died of signal %d", sig);
+			goto error_die;
+		}
+		if (!WIFEXITED(status)) {
+			error("git-index-pack died of unnatural causes %d",
+			      status);
+			goto error_die;
+		}
+		code = WEXITSTATUS(status);
+		if (code) {
+			error("git-index-pack died with error code %d", code);
+			goto error_die;
+		}
+		if (err)
+			goto error_die;
+		break;
+	}
+	hash[40] = 0;
+	if (get_sha1_hex(hash, sha1)) {
+		error("git-index-pack reported nonsense '%s'", hash);
+		goto error_die;
+	}
+	/* Now we have pack in pack_tmp_name[], and
+	 * idx in idx[]; rename them to their final names.
+	 */
+	snprintf(final, sizeof(final),
+		 "%s/pack/pack-%s.pack", get_object_directory(), hash);
+	move_temp_to_file(pack_tmp_name, final);
+	chmod(final, 0444);
+	snprintf(final, sizeof(final),
+		 "%s/pack/pack-%s.idx", get_object_directory(), hash);
+	move_temp_to_file(idx, final);
+	chmod(final, 0444);
+	return 0;
+
+ error_die:
+	unlink(idx);
+	unlink(pack_tmp_name);
+	exit(1);
+}
+
+int receive_unpack_pack(int fd[2], const char *me, int quiet)
+{
+	int status;
+	pid_t pid;
+
+	pid = fork();
+	if (pid < 0)
+		die("%s: unable to fork off git-unpack-objects", me);
+	if (!pid) {
+		dup2(fd[0], 0);
+		close(fd[0]);
+		close(fd[1]);
+		execlp("git-unpack-objects", "git-unpack-objects",
+		       quiet ? "-q" : NULL, NULL);
+		die("git-unpack-objects exec failed");
+	}
+	close(fd[0]);
+	close(fd[1]);
+	while (waitpid(pid, &status, 0) < 0) {
+		if (errno != EINTR)
+			die("waiting for git-unpack-objects: %s",
+			    strerror(errno));
+	}
+	if (WIFEXITED(status)) {
+		int code = WEXITSTATUS(status);
+		if (code)
+			die("git-unpack-objects died with error code %d",
+			    code);
+		return 0;
+	}
+	if (WIFSIGNALED(status)) {
+		int sig = WTERMSIG(status);
+		die("git-unpack-objects died of signal %d", sig);
+	}
+	die("git-unpack-objects died of unnatural causes %d", status);
+}
+
+int receive_keep_pack(int fd[2], const char *me)
+{
+	char tmpfile[PATH_MAX];
+	int ofd, ifd;
+
+	ifd = fd[0];
+	snprintf(tmpfile, sizeof(tmpfile),
+		 "%s/pack/tmp-XXXXXX", get_object_directory());
+	ofd = mkstemp(tmpfile);
+	if (ofd < 0)
+		return error("unable to create temporary file %s", tmpfile);
+
+	while (1) {
+		char buf[8192];
+		ssize_t sz, wsz, pos;
+		sz = read(ifd, buf, sizeof(buf));
+		if (sz == 0)
+			break;
+		if (sz < 0) {
+			error("error reading pack (%s)", strerror(errno));
+			close(ofd);
+			unlink(tmpfile);
+			return -1;
+		}
+		pos = 0;
+		while (pos < sz) {
+			wsz = write(ofd, buf + pos, sz - pos);
+			if (wsz < 0) {
+				error("error writing pack (%s)",
+				      strerror(errno));
+				close(ofd);
+				unlink(tmpfile);
+				return -1;
+			}
+			pos += wsz;
+		}
+	}
+	close(ofd);
+	return finish_pack(tmpfile, me);
+}
 #include "pkt-line.h"
 #include "commit.h"
 #include "tag.h"
-#include <time.h>
-#include <sys/wait.h>
 
+static int keep_pack;
 static int quiet;
 static int verbose;
 static const char fetch_pack_usage[] =
-"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
+"git-fetch-pack [-q] [-v] [-k] [--exec=upload-pack] [host:]directory <refs>...";
 static const char *exec = "git-upload-pack";
 
 #define COMPLETE	(1U << 0)
 	struct ref *ref;
 	unsigned char sha1[20];
 	int status;
-	pid_t pid;
 
 	get_remote_heads(fd[0], &ref, 0, NULL, 0);
 	if (server_supports("multi_ack")) {
 	}
 	if (find_common(fd, sha1, ref) < 0)
 		fprintf(stderr, "warning: no common commits\n");
-	pid = fork();
-	if (pid < 0)
-		die("git-fetch-pack: unable to fork off git-unpack-objects");
-	if (!pid) {
-		dup2(fd[0], 0);
-		close(fd[0]);
-		close(fd[1]);
-		execlp("git-unpack-objects", "git-unpack-objects",
-		       quiet ? "-q" : NULL, NULL);
-		die("git-unpack-objects exec failed");
-	}
-	close(fd[0]);
-	close(fd[1]);
-	while (waitpid(pid, &status, 0) < 0) {
-		if (errno != EINTR)
-			die("waiting for git-unpack-objects: %s", strerror(errno));
-	}
-	if (WIFEXITED(status)) {
-		int code = WEXITSTATUS(status);
-		if (code)
-			die("git-unpack-objects died with error code %d", code);
-all_done:
-		while (ref) {
-			printf("%s %s\n",
-			       sha1_to_hex(ref->old_sha1), ref->name);
-			ref = ref->next;
-		}
-		return 0;
-	}
-	if (WIFSIGNALED(status)) {
-		int sig = WTERMSIG(status);
-		die("git-unpack-objects died of signal %d", sig);
+
+	if (keep_pack)
+		status = receive_keep_pack(fd, "git-fetch-pack");
+	else
+		status = receive_unpack_pack(fd, "git-fetch-pack", quiet);
+
+	if (status)
+		die("git-fetch-pack: fetch failed.");
+
+ all_done:
+	while (ref) {
+		printf("%s %s\n",
+		       sha1_to_hex(ref->old_sha1), ref->name);
+		ref = ref->next;
 	}
-	die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
+	return 0;
 }
 
 int main(int argc, char **argv)
 				exec = arg + 7;
 				continue;
 			}
-			if (!strcmp("-q", arg)) {
+			if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
 				quiet = 1;
 				continue;
 			}
+			if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
+				keep_pack = 1;
+				continue;
+			}
 			if (!strcmp("-v", arg)) {
 				verbose = 1;
 				continue;
 if test "$skip" = t
 then
 	this=`expr "$this" + 1`
+	resume=
 fi
 
 if test "$this" -gt "$last"
 	msgnum=`printf "%0${prec}d" $this`
 	next=`expr "$this" + 1`
 	test -f "$dotest/$msgnum" || {
+		resume=
 		go_next
 		continue
 	}

git-applypatch.sh

 USAGE='<msg> <patch> <info> [<signoff>]'
 . git-sh-setup
 
-case "$#" in 3|4) usage ;; esac
+case "$#" in 3|4) ;; *) usage ;; esac
 
 final=.dotest/final-commit
 ##

git-archimport.perl

 
 =head1 Invocation
 
-    git-archimport [ -h ] [ -v ] [ -T ] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ]
+    git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] 
+    	[ -D depth] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ]
 
 Imports a project from one or more Arch repositories. It will follow branches
 and repositories within the namespaces defined by the <archive/branch>
 sub usage() {
     print STDERR <<END;
 Usage: ${\basename $0}     # fetch/update GIT from Arch
-       [ -f ] [ -o ] [ -h ] [ -v ] [ -T ] [ -a ] [ -D depth  ] [ -t tempdir ]
+       [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] [ -D depth ] [ -t tempdir ]
        repository/arch-branch [ repository/arch-branch] ...
 END
     exit(1);
 	    case " $mbs " in
 	    *' '$branch' '*)
 		# the merge base of branch and HEAD contains branch --
-		# which means that the HEAD contains everything in the HEAD.
+		# which means that the HEAD contains everything in both.
 		;;
 	    *)
 		echo >&2 "The branch '$branch_name' is not a strict subset of your current HEAD.
-    If you are sure you want to delete it, run 'git branch -D $branch_name'."
+If you are sure you want to delete it, run 'git branch -D $branch_name'."
 		exit 1
 		;;
 	    esac
 fi
 
 # 
-# Switch the HEAD pointer to the new branch if it we
+# Switch the HEAD pointer to the new branch if we
 # checked out a branch head, and remove any potential
 # old MERGE_HEAD's (subsequent commits will clearly not
 # be based on them, since we re-set the index)

git-compat-util.h

 	return ret;
 }
 
+static inline ssize_t xread(int fd, void *buf, size_t len)
+{
+	ssize_t nr;
+	while (1) {
+		nr = read(fd, buf, len);
+		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+			continue;
+		return nr;
+	}
+}
+
+static inline ssize_t xwrite(int fd, const void *buf, size_t len)
+{
+	ssize_t nr;
+	while (1) {
+		nr = write(fd, buf, len);
+		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+			continue;
+		return nr;
+	}
+}
+
 /* Sane ctype - no locale, and works with signed chars */
 #undef isspace
 #undef isdigit
 # Copyright (c) 2005 Linus Torvalds
 # Copyright (c) 2005 Junio C Hamano
 
+USAGE='[ --diff-options ] <ent>{0,2} [<path>...]'
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
+
 rev=$(git-rev-parse --revs-only --no-flags --sq "$@") || exit
 flags=$(git-rev-parse --no-revs --flags --sq "$@")
 files=$(git-rev-parse --no-revs --no-flags --sq "$@")
 
-die () {
-    echo >&2 "$*"
-    exit 1
-}
-
 # I often say 'git diff --cached -p' and get scolded by git-diff-files, but
 # obviously I mean 'git diff --cached -p HEAD' in that case.
 case "$rev" in
 
 case "$rev" in
 ?*' '?*' '?*)
-	echo >&2 "I don't understand"
-	exit 1
+	usage
 	;;
 ?*' '^?*)
 	begin=$(expr "$rev" : '.*^.\([0-9a-f]*\).*') &&
 	cmd="git-diff-files $flags -- $files"
 	;;
 *)
-	die "I don't understand $*"
+	usage
 	;;
 esac
 

git-format-patch.sh

 	}
 
 	mailScript="$mailScript"'
+	a\
+
 	: body
 	p
 	n
 # Copyright (c) 2005 Linus Torvalds
 #
 
-# This one uses only subdirectory-aware commands, so no need to
-# include sh-setup-script.
+USAGE='[--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [git-rev-list options]'
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
 
 revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
 [ "$revs" ] || {
-	echo >&2 "No HEAD ref"
-	exit 1
+	die "No HEAD ref"
 }
 git-rev-list --pretty $(git-rev-parse --default HEAD "$@") |
 LESS=-S ${PAGER:-less}

git-octopus.sh

-#!/bin/sh
-#
-# Copyright (c) 2005 Junio C Hamano
-#
-# Resolve two or more trees recorded in $GIT_DIR/FETCH_HEAD.
-#
-. git-sh-setup
-
-usage () {
-    die "usage: git octopus"
-}
-
-# Sanity check the heads early.
-while read SHA1 REPO
-do
-	test $(git-cat-file -t $SHA1) = "commit" ||
-		die "$REPO given to octopus is not a commit"
-done <"$GIT_DIR/FETCH_HEAD"
-
-head=$(git-rev-parse --verify HEAD) || exit
-
-git-update-index --refresh ||
-	die "Your working tree is dirty."
-test "$(git-diff-index --cached "$head")" = "" ||
-	die "Your working tree does not match HEAD."
-
-# MRC is the current "merge reference commit"
-# MRT is the current "merge result tree"
-
-MRC=$head PARENT="-p $head"
-MRT=$(git-write-tree)
-CNT=1 ;# counting our head
-NON_FF_MERGE=0
-while read SHA1 REPO
-do
-	common=$(git-merge-base $MRC $SHA1) ||
-		die "Unable to find common commit with $SHA1 from $REPO"
-
-	if test "$common" = $SHA1
-	then
-		echo "Already up-to-date: $REPO"
-		continue
-	fi
-
-	CNT=`expr $CNT + 1`
-	PARENT="$PARENT -p $SHA1"
-
-	if test "$common,$NON_FF_MERGE" = "$MRC,0"
-	then
-		# The first head being merged was a fast-forward.
-		# Advance MRC to the head being merged, and use that
-		# tree as the intermediate result of the merge.
-		# We still need to count this as part of the parent set.
-
-		echo "Fast forwarding to: $REPO"
-		git-read-tree -u -m $head $SHA1 || exit
-		MRC=$SHA1 MRT=$(git-write-tree)
-		continue
-	fi
-
-	NON_FF_MERGE=1
-
-	echo "Trying simple merge with $REPO"
-	git-read-tree -u -m $common $MRT $SHA1 || exit
-	next=$(git-write-tree 2>/dev/null)
-	if test $? -ne 0
-	then
-		echo "Simple merge did not work, trying automatic merge."
-		git-merge-index -o git-merge-one-file -a || {
-		git-read-tree --reset "$head"
-		git-checkout-index -f -q -u -a
-		die "Automatic merge failed; should not be doing Octopus"
-		}
-		next=$(git-write-tree 2>/dev/null)
-	fi
-	MRC=$common
-	MRT=$next
-done <"$GIT_DIR/FETCH_HEAD"
-
-# Just to be careful in case the user feeds nonsense to us.
-case "$CNT" in
-1)
-	echo "No changes."
-	exit 0 ;;
-esac
-result_commit=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD" |
-		git-commit-tree $MRT $PARENT)
-echo "Committed merge $result_commit"
-git-update-ref HEAD $result_commit $head
-git-diff-tree -p $head $result_commit | git-apply --stat

git-svnimport.perl

 }
 
 $opt_l = $svn->{'maxrev'} if not defined $opt_l or $opt_l > $svn->{'maxrev'};
+
+if ($svn->{'maxrev'} < $current_rev) {
+    print "Up to date: no new revisions to fetch!\n" if $opt_v;
+    unlink("$git_dir/SVN2GIT_HEAD");
+    exit;
+}
+
 print "Fetching from $current_rev to $opt_l ...\n" if $opt_v;
 
 my $pool=SVN::Pool->new;

git-whatchanged.sh

 #!/bin/sh
+
+USAGE='[-p] [--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [-m] [git-diff-tree options] [git-rev-list options]'
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
+
 rev_list_args=$(git-rev-parse --sq --default HEAD --revs-only "$@") &&
 diff_tree_args=$(git-rev-parse --sq --no-revs "$@") &&
 
 #include <errno.h>
 #include <limits.h>
 #include <stdarg.h>
+#include <sys/ioctl.h>
 #include "git-compat-util.h"
 
 #ifndef PATH_MAX
 	if (col_string && (n_cols = atoi(col_string)) > 0)
 		return n_cols;
 
+#ifdef TIOCGWINSZ
+	{
+		struct winsize ws;
+		if (!ioctl(1, TIOCGWINSZ, &ws)) {
+			if (ws.ws_col)
+				return ws.ws_col;
+		}
+	}
+#endif
+
 	return 80;
 }
 
 
 static void pretty_print_string_list(struct cmdname **cmdname, int longest)
 {
-	int cols = 1;
+	int cols = 1, rows;
 	int space = longest + 1; /* min 1 SP between words */
 	int max_cols = term_columns() - 1; /* don't print *on* the edge */
-	int i;
+	int i, j;
 
 	if (space < max_cols)
 		cols = max_cols / space;
+	rows = (cmdname_cnt + cols - 1) / cols;
 
 	qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
 
-	for (i = 0; i < cmdname_cnt; ) {
-		int c;
+	for (i = 0; i < rows; i++) {
 		printf("  ");
 
-		for (c = cols; c && i < cmdname_cnt; i++) {
-			printf("%s", cmdname[i]->name);
-
-			if (--c)
-				mput_char(' ', space - cmdname[i]->len);
+		for (j = 0; j < cols; j++) {
+			int n = j * rows + i;
+			int size = space;
+			if (n >= cmdname_cnt)
+				break;
+			if (j == cols-1 || n + rows >= cmdname_cnt)
+				size = 1;
+			printf("%-*s", size, cmdname[n]->name);
 		}
 		putchar('\n');
 	}
 	// Read the signature
 	size = 0;
 	for (;;) {
-		int ret = read(0, buffer + size, MAXSIZE - size);
-		if (!ret)
+		int ret = xread(0, buffer + size, MAXSIZE - size);
+		if (ret <= 0)
 			break;
-		if (ret < 0) {
-			if (errno == EAGAIN)
-				continue;
-			break;
-		}
 		size += ret;
 	}
 
 static void safe_write(int fd, const void *buf, unsigned n)
 {
 	while (n) {
-		int ret = write(fd, buf, n);
+		int ret = xwrite(fd, buf, n);
 		if (ret > 0) {
 			buf += ret;
 			n -= ret;
 		}
 		if (!ret)
 			die("write error (disk full?)");
-		if (errno == EAGAIN || errno == EINTR)
-			continue;
 		die("write error (%s)", strerror(errno));
 	}
 }
 	int n = 0;
 
 	while (n < size) {
-		int ret = read(fd, buffer + n, size - n);
-		if (ret < 0) {
-			if (errno == EINTR || errno == EAGAIN)
-				continue;
+		int ret = xread(fd, buffer + n, size - n);
+		if (ret < 0)
 			die("read error (%s)", strerror(errno));
-		}
 		if (!ret)
 			die("unexpected EOF");
 		n += ret;
 #include "cache.h"
 
 struct cache_entry **active_cache = NULL;
+static time_t index_file_timestamp;
 unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;
 
 /*
 	ce->ce_size = htonl(st->st_size);
 }
 
-int ce_match_stat(struct cache_entry *ce, struct stat *st)
+static int ce_compare_data(struct cache_entry *ce, struct stat *st)
+{
+	int match = -1;
+	int fd = open(ce->name, O_RDONLY);
+
+	if (fd >= 0) {
+		unsigned char sha1[20];
+		if (!index_fd(sha1, fd, st, 0, NULL))
+			match = memcmp(sha1, ce->sha1, 20);
+		close(fd);
+	}
+	return match;
+}
+
+static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)
+{
+	int match = -1;
+	char *target;
+	void *buffer;
+	unsigned long size;
+	char type[10];
+	int len;
+
+	target = xmalloc(expected_size);
+	len = readlink(ce->name, target, expected_size);
+	if (len != expected_size) {
+		free(target);
+		return -1;
+	}
+	buffer = read_sha1_file(ce->sha1, type, &size);
+	if (!buffer) {
+		free(target);
+		return -1;
+	}
+	if (size == expected_size)
+		match = memcmp(buffer, target, size);
+	free(buffer);
+	free(target);
+	return match;
+}
+
+static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
+{
+	switch (st->st_mode & S_IFMT) {
+	case S_IFREG:
+		if (ce_compare_data(ce, st))
+			return DATA_CHANGED;
+		break;
+	case S_IFLNK:
+		if (ce_compare_link(ce, st->st_size))
+			return DATA_CHANGED;
+		break;
+	default:
+		return TYPE_CHANGED;
+	}
+	return 0;
+}
+
+static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
 {
 	unsigned int changed = 0;
 
 
 	if (ce->ce_size != htonl(st->st_size))
 		changed |= DATA_CHANGED;
+
 	return changed;
 }
 
-static int ce_compare_data(struct cache_entry *ce, struct stat *st)
+int ce_match_stat(struct cache_entry *ce, struct stat *st)
 {
-	int match = -1;
-	int fd = open(ce->name, O_RDONLY);
+	unsigned int changed = ce_match_stat_basic(ce, st);
 
-	if (fd >= 0) {
-		unsigned char sha1[20];
-		if (!index_fd(sha1, fd, st, 0, NULL))
-			match = memcmp(sha1, ce->sha1, 20);
-		close(fd);
-	}
-	return match;
-}
-
-static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)
-{
-	int match = -1;
-	char *target;
-	void *buffer;
-	unsigned long size;
-	char type[10];
-	int len;
+	/*
+	 * Within 1 second of this sequence:
+	 * 	echo xyzzy >file && git-update-index --add file
+	 * running this command:
+	 * 	echo frotz >file
+	 * would give a falsely clean cache entry.  The mtime and
+	 * length match the cache, and other stat fields do not change.
+	 *
+	 * We could detect this at update-index time (the cache entry
+	 * being registered/updated records the same time as "now")
+	 * and delay the return from git-update-index, but that would
+	 * effectively mean we can make at most one commit per second,
+	 * which is not acceptable.  Instead, we check cache entries
+	 * whose mtime are the same as the index file timestamp more
+	 * careful than others.