Merge branch 'cc/replace'
authorJunio C Hamano <gitster@pobox.com>
Sat, 22 Aug 2009 01:47:53 +0000 (18:47 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 22 Aug 2009 01:47:53 +0000 (18:47 -0700)
* cc/replace:
t6050: check pushing something based on a replaced commit
Documentation: add documentation for "git replace"
Add git-replace to .gitignore
builtin-replace: use "usage_msg_opt" to give better error messages
parse-options: add new function "usage_msg_opt"
builtin-replace: teach "git replace" to actually replace
Add new "git replace" command
environment: add global variable to disable replacement
mktag: call "check_sha1_signature" with the replacement sha1
replace_object: add a test case
object: call "check_sha1_signature" with the replacement sha1
sha1_file: add a "read_sha1_file_repl" function
replace_object: add mechanism to replace objects found in "refs/replace/"
refs: add a "for_each_replace_ref" function

15 files changed:
1  2 
Makefile
builtin-fsck.c
builtin-pack-objects.c
builtin-unpack-objects.c
builtin.h
cache.h
commit.h
environment.c
git.c
mktag.c
parse-options.c
parse-options.h
refs.c
sha1_file.c
upload-pack.c
diff --combined Makefile
index e6df8ecde68edbfddf7266de3aa11912df63b30e,6c46629b8c5d0b92ad7f905f64458ce6ac7b8c3e..66eedeff428986e2d5850ac84c98cd0ab7a44081
+++ b/Makefile
@@@ -3,11 -3,6 +3,11 @@@ all:
  
  # Define V=1 to have a more verbose compile.
  #
 +# Define SHELL_PATH to a POSIX shell if your /bin/sh is broken.
 +#
 +# Define SANE_TOOL_PATH to a colon-separated list of paths to prepend
 +# to PATH if your tools in /usr/bin are broken.
 +#
  # Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
  # or vsnprintf() return -1 instead of number of characters which would
  # have been written to the final string if enough space had been available.
  #
  # Define NO_MKDTEMP if you don't have mkdtemp in the C library.
  #
 +# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
 +#
 +# Define NO_LIBGEN_H if you don't have libgen.h.
 +#
 +# Define NEEDS_LIBGEN if your libgen needs -lgen when linking
 +#
  # Define NO_SYS_SELECT_H if you don't have sys/select.h.
  #
  # Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
  # specify your own (or DarwinPort's) include directories and
  # library directories by defining CFLAGS and LDFLAGS appropriately.
  #
 +# Define BLK_SHA1 environment variable if you want the C version
 +# of the SHA1 that assumes you can do unaligned 32-bit loads and
 +# have a fast htonl() function.
 +#
  # Define PPC_SHA1 environment variable when running make to make use of
  # a bundled SHA1 routine optimized for PowerPC.
  #
  # Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
  # Patrick Mauritz).
  #
 +# Define NEEDS_RESOLV if linking with -lnsl and/or -lsocket is not enough.
 +# Notably on Solaris hstrerror resides in libresolv and on Solaris 7
 +# inet_ntop and inet_pton additionally reside there.
 +#
  # Define NO_MMAP if you want to avoid mmap.
  #
  # Define NO_PTHREADS if you do not have or do not want to use Pthreads.
  #
  # Define NO_CROSS_DIRECTORY_HARDLINKS if you plan to distribute the installed
  # programs as a tar, where bin/ and libexec/ might be on different file systems.
 +#
 +# Define USE_NED_ALLOCATOR if you want to replace the platforms default
 +# memory allocators with the nedmalloc allocator written by Niall Douglas.
 +#
 +# Define NO_REGEX if you have no or inferior regex support in your C library.
  
  GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@@ -536,6 -512,7 +536,7 @@@ LIB_OBJS += read-cache.
  LIB_OBJS += reflog-walk.o
  LIB_OBJS += refs.o
  LIB_OBJS += remote.o
+ LIB_OBJS += replace_object.o
  LIB_OBJS += rerere.o
  LIB_OBJS += revision.o
  LIB_OBJS += run-command.o
@@@ -625,6 -602,7 +626,7 @@@ BUILTIN_OBJS += builtin-read-tree.
  BUILTIN_OBJS += builtin-receive-pack.o
  BUILTIN_OBJS += builtin-reflog.o
  BUILTIN_OBJS += builtin-remote.o
+ BUILTIN_OBJS += builtin-replace.o
  BUILTIN_OBJS += builtin-rerere.o
  BUILTIN_OBJS += builtin-reset.o
  BUILTIN_OBJS += builtin-rev-list.o
@@@ -660,12 -638,10 +662,12 @@@ EXTLIBS 
  
  ifeq ($(uname_S),Linux)
        NO_STRLCPY = YesPlease
 +      NO_MKSTEMPS = YesPlease
        THREADED_DELTA_SEARCH = YesPlease
  endif
  ifeq ($(uname_S),GNU/kFreeBSD)
        NO_STRLCPY = YesPlease
 +      NO_MKSTEMPS = YesPlease
        THREADED_DELTA_SEARCH = YesPlease
  endif
  ifeq ($(uname_S),UnixWare)
        SHELL_PATH = /usr/local/bin/bash
        NO_IPV6 = YesPlease
        NO_HSTRERROR = YesPlease
 +      NO_MKSTEMPS = YesPlease
        BASIC_CFLAGS += -Kthread
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
@@@ -701,7 -676,6 +703,7 @@@ ifeq ($(uname_S),SCO_SV
        SHELL_PATH = /usr/bin/bash
        NO_IPV6 = YesPlease
        NO_HSTRERROR = YesPlease
 +      NO_MKSTEMPS = YesPlease
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
        NO_STRCASESTR = YesPlease
@@@ -726,22 -700,12 +728,22 @@@ ifeq ($(uname_S),SunOS
        NEEDS_SOCKET = YesPlease
        NEEDS_NSL = YesPlease
        SHELL_PATH = /bin/bash
 +      SANE_TOOL_PATH = /usr/xpg6/bin:/usr/xpg4/bin
        NO_STRCASESTR = YesPlease
        NO_MEMMEM = YesPlease
 -      NO_HSTRERROR = YesPlease
        NO_MKDTEMP = YesPlease
 -      ifneq ($(uname_R),5.11)
 -              OLD_ICONV = UnfortunatelyYes
 +      NO_MKSTEMPS = YesPlease
 +      NO_REGEX = YesPlease
 +      NO_EXTERNAL_GREP = YesPlease
 +      ifeq ($(uname_R),5.7)
 +              NEEDS_RESOLV = YesPlease
 +              NO_IPV6 = YesPlease
 +              NO_SOCKADDR_STORAGE = YesPlease
 +              NO_UNSETENV = YesPlease
 +              NO_SETENV = YesPlease
 +              NO_STRLCPY = YesPlease
 +              NO_C99_FORMAT = YesPlease
 +              NO_STRTOUMAX = YesPlease
        endif
        ifeq ($(uname_R),5.8)
                NO_UNSETENV = YesPlease
                NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
        endif
 -      INSTALL = ginstall
 +      ifdef NO_IPV6
 +              NEEDS_RESOLV = YesPlease
 +      endif
 +      INSTALL = /usr/ucb/install
        TAR = gtar
 -      BASIC_CFLAGS += -D__EXTENSIONS__
 +      BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
  endif
  ifeq ($(uname_O),Cygwin)
        NO_D_TYPE_IN_DIRENT = YesPlease
        NO_D_INO_IN_DIRENT = YesPlease
        NO_STRCASESTR = YesPlease
        NO_MEMMEM = YesPlease
 +      NO_MKSTEMPS = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NEEDS_LIBICONV = YesPlease
        NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@@@ -811,13 -771,11 +813,13 @@@ ifeq ($(uname_S),NetBSD
        BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
        THREADED_DELTA_SEARCH = YesPlease
        USE_ST_TIMESPEC = YesPlease
 +      NO_MKSTEMPS = YesPlease
  endif
  ifeq ($(uname_S),AIX)
        NO_STRCASESTR=YesPlease
        NO_MEMMEM = YesPlease
        NO_MKDTEMP = YesPlease
 +      NO_MKSTEMPS = YesPlease
        NO_STRLCPY = YesPlease
        NO_NSEC = YesPlease
        FREAD_READS_DIRECTORIES = UnfortunatelyYes
@@@ -833,40 -791,24 +835,40 @@@ endi
  ifeq ($(uname_S),GNU)
        # GNU/Hurd
        NO_STRLCPY=YesPlease
 +      NO_MKSTEMPS = YesPlease
 +endif
 +ifeq ($(uname_S),IRIX)
 +      NO_SETENV = YesPlease
 +      NO_UNSETENV = YesPlease
 +      NO_STRCASESTR = YesPlease
 +      NO_MEMMEM = YesPlease
 +      NO_MKSTEMPS = YesPlease
 +      NO_MKDTEMP = YesPlease
 +      NO_MMAP = YesPlease
 +      NO_EXTERNAL_GREP = UnfortunatelyYes
 +      SNPRINTF_RETURNS_BOGUS = YesPlease
 +      SHELL_PATH = /usr/gnu/bin/bash
 +      NEEDS_LIBGEN = YesPlease
  endif
  ifeq ($(uname_S),IRIX64)
 -      NO_IPV6=YesPlease
        NO_SETENV=YesPlease
 +      NO_UNSETENV = YesPlease
        NO_STRCASESTR=YesPlease
        NO_MEMMEM = YesPlease
 -      NO_STRLCPY = YesPlease
 -      NO_SOCKADDR_STORAGE=YesPlease
 +      NO_MKSTEMPS = YesPlease
 +      NO_MKDTEMP = YesPlease
 +      NO_MMAP = YesPlease
 +      NO_EXTERNAL_GREP = UnfortunatelyYes
 +      SNPRINTF_RETURNS_BOGUS = YesPlease
        SHELL_PATH=/usr/gnu/bin/bash
 -      BASIC_CFLAGS += -DPATH_MAX=1024
 -      # for now, build 32-bit version
 -      BASIC_LDFLAGS += -L/usr/lib32
 +      NEEDS_LIBGEN = YesPlease
  endif
  ifeq ($(uname_S),HP-UX)
        NO_IPV6=YesPlease
        NO_SETENV=YesPlease
        NO_STRCASESTR=YesPlease
        NO_MEMMEM = YesPlease
 +      NO_MKSTEMPS = YesPlease
        NO_STRLCPY = YesPlease
        NO_MKDTEMP = YesPlease
        NO_UNSETENV = YesPlease
@@@ -882,7 -824,7 +884,7 @@@ ifneq (,$(findstring MINGW,$(uname_S))
        pathsep = ;
        NO_PREAD = YesPlease
        NO_OPENSSL = YesPlease
 -      NO_CURL = YesPlease
 +      NO_LIBGEN_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_IPV6 = YesPlease
        NO_SETENV = YesPlease
        NO_STRCASESTR = YesPlease
        NO_STRLCPY = YesPlease
        NO_MEMMEM = YesPlease
 -      NO_PTHREADS = YesPlease
        NEEDS_LIBICONV = YesPlease
        OLD_ICONV = YesPlease
        NO_C99_FORMAT = YesPlease
        NO_STRTOUMAX = YesPlease
        NO_MKDTEMP = YesPlease
 +      NO_MKSTEMPS = YesPlease
        SNPRINTF_RETURNS_BOGUS = YesPlease
        NO_SVN_TESTS = YesPlease
        NO_PERL_MAKEMAKER = YesPlease
        NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
        NO_NSEC = YesPlease
        USE_WIN32_MMAP = YesPlease
 +      USE_NED_ALLOCATOR = YesPlease
        UNRELIABLE_FSTAT = UnfortunatelyYes
        OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
 -      COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
 -      COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
 +      NO_REGEX = YesPlease
 +      COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 -      COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/regex/regex.o compat/winansi.o
 +      COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
        EXTLIBS += -lws2_32
        X = .exe
 +ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
 +      htmldir=doc/git/html/
 +      prefix =
 +      INSTALL = /bin/install
 +      EXTLIBS += /mingw/lib/libz.a
 +      NO_R_TO_GCC_LINKER = YesPlease
 +      INTERNAL_QSORT = YesPlease
 +      THREADED_DELTA_SEARCH = YesPlease
 +else
 +      NO_CURL = YesPlease
 +      NO_PTHREADS = YesPlease
 +endif
  endif
  ifneq (,$(findstring arm,$(uname_M)))
        ARM_SHA1 = YesPlease
 +      NO_MKSTEMPS = YesPlease
  endif
  
  -include config.mak.autogen
  -include config.mak
  
 +ifdef SANE_TOOL_PATH
 +SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
 +BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix $(SANE_TOOL_PATH_SQ)|'
 +PATH := $(SANE_TOOL_PATH):${PATH}
 +else
 +BROKEN_PATH_FIX = '/^\# @@BROKEN_PATH_FIX@@$$/d'
 +endif
 +
  ifeq ($(uname_S),Darwin)
        ifndef NO_FINK
                ifeq ($(shell test -d /sw/lib && echo y),y)
@@@ -968,11 -888,6 +970,11 @@@ ifndef CC_LD_DYNPAT
        endif
  endif
  
 +ifdef NO_LIBGEN_H
 +      COMPAT_CFLAGS += -DNO_LIBGEN_H
 +      COMPAT_OBJS += compat/basename.o
 +endif
 +
  ifdef NO_CURL
        BASIC_CFLAGS += -DNO_CURL
  else
@@@ -1039,18 -954,12 +1041,18 @@@ ifdef NEEDS_LIBICON
        endif
        EXTLIBS += $(ICONV_LINK) -liconv
  endif
 +ifdef NEEDS_LIBGEN
 +      EXTLIBS += -lgen
 +endif
  ifdef NEEDS_SOCKET
        EXTLIBS += -lsocket
  endif
  ifdef NEEDS_NSL
        EXTLIBS += -lnsl
  endif
 +ifdef NEEDS_RESOLV
 +      EXTLIBS += -lresolv
 +endif
  ifdef NO_D_TYPE_IN_DIRENT
        BASIC_CFLAGS += -DNO_D_TYPE_IN_DIRENT
  endif
@@@ -1106,10 -1015,6 +1108,10 @@@ ifdef NO_MKDTEM
        COMPAT_CFLAGS += -DNO_MKDTEMP
        COMPAT_OBJS += compat/mkdtemp.o
  endif
 +ifdef NO_MKSTEMPS
 +      COMPAT_CFLAGS += -DNO_MKSTEMPS
 +      COMPAT_OBJS += compat/mkstemps.o
 +endif
  ifdef NO_UNSETENV
        COMPAT_CFLAGS += -DNO_UNSETENV
        COMPAT_OBJS += compat/unsetenv.o
@@@ -1171,10 -1076,6 +1173,10 @@@ ifdef NO_DEFLATE_BOUN
        BASIC_CFLAGS += -DNO_DEFLATE_BOUND
  endif
  
 +ifdef BLK_SHA1
 +      SHA1_HEADER = "block-sha1/sha1.h"
 +      LIB_OBJS += block-sha1/sha1.o
 +else
  ifdef PPC_SHA1
        SHA1_HEADER = "ppc/sha1.h"
        LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
@@@ -1192,7 -1093,6 +1194,7 @@@ els
  endif
  endif
  endif
 +endif
  ifdef NO_PERL_MAKEMAKER
        export NO_PERL_MAKEMAKER
  endif
@@@ -1232,15 -1132,6 +1234,15 @@@ endi
  ifdef UNRELIABLE_FSTAT
        BASIC_CFLAGS += -DUNRELIABLE_FSTAT
  endif
 +ifdef NO_REGEX
 +      COMPAT_CFLAGS += -Icompat/regex
 +      COMPAT_OBJS += compat/regex/regex.o
 +endif
 +
 +ifdef USE_NED_ALLOCATOR
 +       COMPAT_CFLAGS += -DUSE_NED_ALLOCATOR -DOVERRIDE_STRDUP -DNDEBUG -DREPLACE_SYSTEM_ALLOCATOR -Icompat/nedmalloc
 +       COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
 +endif
  
  ifeq ($(TCLTK_PATH),)
  NO_TCLTK=NoThanks
@@@ -1316,7 -1207,7 +1318,7 @@@ SHELL = $(SHELL_PATH
  
  all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
  ifneq (,$X)
 -      $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
 +      $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
  endif
  
  all::
@@@ -1369,7 -1260,6 +1371,7 @@@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %
            -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
            -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
            -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
 +          -e $(BROKEN_PATH_FIX) \
            $@.sh >$@+ && \
        chmod +x $@+ && \
        mv $@+ $@
@@@ -1500,7 -1390,7 +1502,7 @@@ git-http-push$X: revision.o http.o http
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
  
  $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
 -$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
 +$(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h)
  builtin-revert.o wt-status.o: wt-status.h
  
  $(LIB_FILE): $(LIB_OBJS)
@@@ -1609,8 -1499,6 +1611,8 @@@ test-delta$X: diff-delta.o patch-delta.
  
  test-parse-options$X: parse-options.o
  
 +test-parse-options.o: parse-options.h
 +
  .PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
  
  test-%$X: test-%.o $(GITLIBS)
@@@ -1669,16 -1557,15 +1671,16 @@@ ifneq (,$X
  endif
        bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
        execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
 -      { $(RM) "$$execdir/git-add$X" && \
 +      { test "$$bindir/" = "$$execdir/" || \
 +              { $(RM) "$$execdir/git$X" && \
                test -z "$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
 -              ln "$$bindir/git$X" "$$execdir/git-add$X" 2>/dev/null || \
 -              cp "$$bindir/git$X" "$$execdir/git-add$X"; } && \
 -      { for p in $(filter-out git-add$X,$(BUILT_INS)); do \
 +              ln "$$bindir/git$X" "$$execdir/git$X" 2>/dev/null || \
 +              cp "$$bindir/git$X" "$$execdir/git$X"; } ; } && \
 +      { for p in $(BUILT_INS); do \
                $(RM) "$$execdir/$$p" && \
 -              ln "$$execdir/git-add$X" "$$execdir/$$p" 2>/dev/null || \
 -              ln -s "git-add$X" "$$execdir/$$p" 2>/dev/null || \
 -              cp "$$execdir/git-add$X" "$$execdir/$$p" || exit; \
 +              ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
 +              ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
 +              cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
          done; } && \
        ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
  
@@@ -1759,7 -1646,7 +1761,7 @@@ distclean: clea
        $(RM) configure
  
  clean:
 -      $(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \
 +      $(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \
                $(LIB_FILE) $(XDIFF_LIB)
        $(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS)
diff --combined builtin-fsck.c
index b3d38fa277b3d0024b9c46a62cf15bc2448cc1e7,bc05de6800fe3d6ce9f636404efff553b1dc8f06..c58b0e337ed434ffb90cfb5c80540531d94a4a6a
@@@ -104,7 -104,7 +104,7 @@@ static int mark_object(struct object *o
  
  static void mark_object_reachable(struct object *obj)
  {
 -      mark_object(obj, OBJ_ANY, 0);
 +      mark_object(obj, OBJ_ANY, NULL);
  }
  
  static int traverse_one_object(struct object *obj, struct object *parent)
@@@ -217,7 -217,7 +217,7 @@@ static void check_unreachable_object(st
                                return;
                        }
                        if (!(f = fopen(filename, "w")))
 -                              die("Could not open %s", filename);
 +                              die_errno("Could not open '%s'", filename);
                        if (obj->type == OBJ_BLOB) {
                                enum object_type type;
                                unsigned long size;
                                                &type, &size);
                                if (buf) {
                                        if (fwrite(buf, size, 1, f) != 1)
 -                                              die("Could not write %s: %s",
 -                                                  filename, strerror(errno));
 +                                              die_errno("Could not write '%s'",
 +                                                        filename);
                                        free(buf);
                                }
                        } else
                                fprintf(f, "%s\n", sha1_to_hex(obj->sha1));
                        if (fclose(f))
 -                              die("Could not finish %s: %s",
 -                                  filename, strerror(errno));
 +                              die_errno("Could not finish '%s'",
 +                                        filename);
                }
                return;
        }
@@@ -292,7 -292,7 +292,7 @@@ static int fsck_sha1(const unsigned cha
                fprintf(stderr, "Checking %s %s\n",
                        typename(obj->type), sha1_to_hex(obj->sha1));
  
 -      if (fsck_walk(obj, mark_used, 0))
 +      if (fsck_walk(obj, mark_used, NULL))
                objerror(obj, "broken links");
        if (fsck_object(obj, check_strict, fsck_error_func))
                return -1;
@@@ -589,6 -589,7 +589,7 @@@ int cmd_fsck(int argc, const char **arg
        struct alternate_object_database *alt;
  
        errors_found = 0;
+       read_replace_refs = 0;
  
        argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
        if (write_lost_and_found) {
diff --combined builtin-pack-objects.c
index 9cc8a8451d21840b315d1355207293a1b0bcbf2c,b2c93d3d212055dd097ce696dea8f3beba6afc6a..c4337480fd3ebbe86919b3014316143ecfa0ccaf
@@@ -86,7 -86,7 +86,7 @@@ static int pack_compression_level = Z_D
  static int pack_compression_seen;
  
  static unsigned long delta_cache_size = 0;
 -static unsigned long max_delta_cache_size = 0;
 +static unsigned long max_delta_cache_size = 256 * 1024 * 1024;
  static unsigned long cache_max_small_delta_size = 1000;
  
  static unsigned long window_memory_limit = 0;
@@@ -536,9 -536,11 +536,9 @@@ static void write_pack_file(void
                                 base_name, sha1_to_hex(sha1));
                        free_pack_by_name(tmpname);
                        if (adjust_perm(pack_tmp_name, mode))
 -                              die("unable to make temporary pack file readable: %s",
 -                                  strerror(errno));
 +                              die_errno("unable to make temporary pack file readable");
                        if (rename(pack_tmp_name, tmpname))
 -                              die("unable to rename temporary pack file: %s",
 -                                  strerror(errno));
 +                              die_errno("unable to rename temporary pack file");
  
                        /*
                         * Packs are runtime accessed in their mtime
                        snprintf(tmpname, sizeof(tmpname), "%s-%s.idx",
                                 base_name, sha1_to_hex(sha1));
                        if (adjust_perm(idx_tmp_name, mode))
 -                              die("unable to make temporary index file readable: %s",
 -                                  strerror(errno));
 +                              die_errno("unable to make temporary index file readable");
                        if (rename(idx_tmp_name, tmpname))
 -                              die("unable to rename temporary index file: %s",
 -                                  strerror(errno));
 +                              die_errno("unable to rename temporary index file");
  
                        free(idx_tmp_name);
                        free(pack_tmp_name);
@@@ -649,7 -653,8 +649,7 @@@ static void rehash_objects(void
  
  static unsigned name_hash(const char *name)
  {
 -      unsigned char c;
 -      unsigned hash = 0;
 +      unsigned c, hash = 0;
  
        if (!name)
                return 0;
@@@ -1875,7 -1880,7 +1875,7 @@@ static void read_object_list_from_stdin
                        if (!ferror(stdin))
                                die("fgets returned NULL, not EOF, not error!");
                        if (errno != EINTR)
 -                              die("fgets: %s", strerror(errno));
 +                              die_errno("fgets");
                        clearerr(stdin);
                        continue;
                }
@@@ -2098,6 -2103,8 +2098,8 @@@ int cmd_pack_objects(int argc, const ch
        int rp_ac_alloc = 64;
        int rp_ac;
  
+       read_replace_refs = 0;
        rp_av = xcalloc(rp_ac_alloc, sizeof(*rp_av));
  
        rp_av[0] = "pack-objects";
                                die("bad %s", arg);
                        continue;
                }
 +              if (!strcmp(arg, "--keep-true-parents")) {
 +                      grafts_replace_parents = 0;
 +                      continue;
 +              }
                usage(pack_usage);
        }
  
diff --combined builtin-unpack-objects.c
index 557148a693c058f51222cb3d996c309791d43d8b,c9f5ac0c340a700a6ddbe4cd0bf9dd69ee2c5945..968fda7219807de9985c06eccd0812da04a149ae
@@@ -68,7 -68,7 +68,7 @@@ static void *fill(int min
                if (ret <= 0) {
                        if (!ret)
                                die("early EOF");
 -                      die("read error on input: %s", strerror(errno));
 +                      die_errno("read error on input");
                }
                len += ret;
        } while (len < min);
@@@ -158,7 -158,7 +158,7 @@@ struct obj_info 
  #define FLAG_WRITTEN (1u<<21)
  
  static struct obj_info *obj_list;
 -unsigned nr_objects;
 +static unsigned nr_objects;
  
  /*
   * Called only from check_object() after it verified this object
@@@ -200,7 -200,7 +200,7 @@@ static int check_object(struct object *
  
        if (fsck_object(obj, 1, fsck_error_function))
                die("Error in object");
 -      if (!fsck_walk(obj, check_object, 0))
 +      if (!fsck_walk(obj, check_object, NULL))
                die("Error on reachable objects of %s", sha1_to_hex(obj->sha1));
        write_cached_object(obj);
        return 1;
@@@ -210,7 -210,7 +210,7 @@@ static void write_rest(void
  {
        unsigned i;
        for (i = 0; i < nr_objects; i++)
 -              check_object(obj_list[i].obj, OBJ_ANY, 0);
 +              check_object(obj_list[i].obj, OBJ_ANY, NULL);
  }
  
  static void added_object(unsigned nr, enum object_type type,
@@@ -422,8 -422,8 +422,8 @@@ static void unpack_delta_entry(enum obj
  static void unpack_one(unsigned nr)
  {
        unsigned shift;
 -      unsigned char *pack, c;
 -      unsigned long size;
 +      unsigned char *pack;
 +      unsigned long size, c;
        enum object_type type;
  
        obj_list[nr].offset = consumed_bytes;
@@@ -495,6 -495,8 +495,8 @@@ int cmd_unpack_objects(int argc, const 
        int i;
        unsigned char sha1[20];
  
+       read_replace_refs = 0;
        git_config(git_default_config, NULL);
  
        quiet = !isatty(2);
diff --combined builtin.h
index 9993dfcf99f7ad47a1a0a052d591cfc06a9f614d,38ceddc53d76d71b8904c7d12dd511f38bb8061b..51e4ba7f360338e5cd666c01c2f3b8c31e9b5a3e
+++ b/builtin.h
@@@ -13,6 -13,7 +13,6 @@@ extern const char git_more_info_string[
  extern void list_common_cmds_help(void);
  extern const char *help_unknown_cmd(const char *cmd);
  extern void prune_packed_objects(int);
 -extern int read_line_with_nul(char *buf, int size, FILE *file);
  extern int fmt_merge_msg(int merge_summary, struct strbuf *in,
        struct strbuf *out);
  extern int commit_tree(const char *msg, unsigned char *tree,
@@@ -111,5 -112,6 +111,6 @@@ extern int cmd_write_tree(int argc, con
  extern int cmd_verify_pack(int argc, const char **argv, const char *prefix);
  extern int cmd_show_ref(int argc, const char **argv, const char *prefix);
  extern int cmd_pack_refs(int argc, const char **argv, const char *prefix);
+ extern int cmd_replace(int argc, const char **argv, const char *prefix);
  
  #endif
diff --combined cache.h
index eee717c81b5882bd59009fb52d0484f0fb1041cb,91ef34071e7f13b86c14da3c3b64afa488bb9d40..f7937893773a4b015df7fafc605e2d561139c86b
+++ b/cache.h
@@@ -468,9 -468,6 +468,9 @@@ extern int index_fd(unsigned char *sha1
  extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
  extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
  
 +/* "careful lstat()" */
 +extern int check_path(const char *path, int len, struct stat *st);
 +
  #define REFRESH_REALLY                0x0001  /* ignore_valid */
  #define REFRESH_UNMERGED      0x0002  /* allow unmerged */
  #define REFRESH_QUIET         0x0004  /* be quiet about it */
@@@ -512,7 -509,6 +512,7 @@@ extern int log_all_ref_updates
  extern int warn_ambiguous_refs;
  extern int shared_repository;
  extern const char *apply_default_whitespace;
 +extern const char *apply_default_ignorewhitespace;
  extern int zlib_compression_level;
  extern int core_compression_level;
  extern int core_compression_seen;
@@@ -520,6 -516,7 +520,7 @@@ extern size_t packed_git_window_size
  extern size_t packed_git_limit;
  extern size_t delta_base_cache_limit;
  extern int auto_crlf;
+ extern int read_replace_refs;
  extern int fsync_object_files;
  extern int core_preload_index;
  
@@@ -547,6 -544,7 +548,6 @@@ enum rebase_setup_type 
  };
  
  enum push_default_type {
 -      PUSH_DEFAULT_UNSPECIFIED = -1,
        PUSH_DEFAULT_NOTHING = 0,
        PUSH_DEFAULT_MATCHING,
        PUSH_DEFAULT_TRACKING,
@@@ -564,8 -562,6 +565,8 @@@ enum object_creation_mode 
  
  extern enum object_creation_mode object_creation_mode;
  
 +extern int grafts_replace_parents;
 +
  #define GIT_REPO_VERSION 0
  extern int repository_format_version;
  extern int check_repository_format(void);
@@@ -619,8 -615,6 +620,8 @@@ extern int is_empty_blob_sha1(const uns
  
  int git_mkstemp(char *path, size_t n, const char *template);
  
 +int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);
 +
  /*
   * NOTE NOTE NOTE!!
   *
@@@ -656,7 -650,11 +657,11 @@@ char *strip_path_suffix(const char *pat
  
  /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
  extern int sha1_object_info(const unsigned char *, unsigned long *);
- extern void * read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size);
+ extern void *read_sha1_file_repl(const unsigned char *sha1, enum object_type *type, unsigned long *size, const unsigned char **replacement);
+ static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
+ {
+       return read_sha1_file_repl(sha1, type, size, NULL);
+ }
  extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1);
  extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
  extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
@@@ -749,17 -747,7 +754,17 @@@ struct checkout 
  };
  
  extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
 +
 +struct cache_def {
 +      char path[PATH_MAX + 1];
 +      int len;
 +      int flags;
 +      int track_flags;
 +      int prefix_len_stat_func;
 +};
 +
  extern int has_symlink_leading_path(const char *name, int len);
 +extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
  extern int has_symlink_or_noent_leading_path(const char *name, int len);
  extern int has_dirs_only_path(const char *name, int len, int prefix_len);
  extern void invalidate_lstat_cache(const char *name, int len);
diff --combined commit.h
index 4886544b631bd6b79ad8410fa369e41975c0ff23,a8bdd090968ce3b3ed07c947b8f6f7259c9944cb..d1674d7f16465b6288fe5e20b03f77dd3a403546
+++ b/commit.h
@@@ -40,6 -40,8 +40,6 @@@ int parse_commit_buffer(struct commit *
  
  int parse_commit(struct commit *item);
  
 -void unparse_commit(struct commit *item);
 -
  struct commit_list * commit_list_insert(struct commit *item, struct commit_list **list_p);
  unsigned commit_list_count(const struct commit_list *l);
  struct commit_list * insert_by_date(struct commit *item, struct commit_list **list);
@@@ -64,7 -66,6 +64,7 @@@ enum cmit_fmt 
  };
  
  extern int non_ascii(int);
 +extern int has_non_ascii(const char *text);
  struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
  extern char *reencode_commit_message(const struct commit *commit,
                                     const char **encoding_p);
@@@ -123,6 -124,8 +123,8 @@@ struct commit_graft *read_graft_line(ch
  int register_commit_graft(struct commit_graft *, int);
  struct commit_graft *lookup_commit_graft(const unsigned char *sha1);
  
+ const unsigned char *lookup_replace_object(const unsigned char *sha1);
  extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);
  extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup);
  extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
diff --combined environment.c
index 3cf88f58c4adad2aef67cd8ced121fef9cd8bab0,6d90074648825701eea33a2e9c1436aaff6854d2..5de683784039f20b55f58ef36cb04a11f6a10610
@@@ -26,7 -26,6 +26,7 @@@ const char *git_commit_encoding
  const char *git_log_output_encoding;
  int shared_repository = PERM_UMASK;
  const char *apply_default_whitespace;
 +const char *apply_default_ignorewhitespace;
  int zlib_compression_level = Z_BEST_SPEED;
  int core_compression_level;
  int core_compression_seen;
@@@ -39,16 -38,16 +39,17 @@@ int pager_use_color = 1
  const char *editor_program;
  const char *excludes_file;
  int auto_crlf = 0;    /* 1: both ways, -1: only when adding git objects */
+ int read_replace_refs = 1;
  enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
  unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
  enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
  enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
 -enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
 +enum push_default_type push_default = PUSH_DEFAULT_MATCHING;
  #ifndef OBJECT_CREATION_MODE
  #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
  #endif
  enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
 +int grafts_replace_parents = 1;
  
  /* Parallel index stat data preload? */
  int core_preload_index = 0;
diff --combined git.c
index 4588a8bac21a12240c84eac4b24d68cb72920d80,8695d67f2a8c9755761539c7bdff72fa2721a07b..5da6c65697dfd198e27b5b693566158bf772ab88
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -188,9 -188,10 +188,9 @@@ static int handle_alias(int *argcp, con
                                  alias_command);
  
                new_argv = xrealloc(new_argv, sizeof(char *) *
 -                                  (count + *argcp + 1));
 +                                  (count + *argcp));
                /* insert after command name */
                memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
 -              new_argv[count+*argcp] = NULL;
  
                *argv = new_argv;
                *argcp += count - 1;
        }
  
        if (subdir && chdir(subdir))
 -              die("Cannot change to %s: %s", subdir, strerror(errno));
 +              die_errno("Cannot change to '%s'", subdir);
  
        errno = saved_errno;
  
@@@ -245,7 -246,7 +245,7 @@@ static int run_builtin(struct cmd_struc
  
        status = p->fn(argc, argv, prefix);
        if (status)
 -              return status & 0xff;
 +              return status;
  
        /* Somebody closed stdout? */
        if (fstat(fileno(stdout), &st))
  
        /* Check for ENOSPC and EIO errors.. */
        if (fflush(stdout))
 -              die("write failure on standard output: %s", strerror(errno));
 +              die_errno("write failure on standard output");
        if (ferror(stdout))
                die("unknown write failure on standard output");
        if (fclose(stdout))
 -              die("close failed on standard output: %s", strerror(errno));
 +              die_errno("close failed on standard output");
        return 0;
  }
  
@@@ -339,6 -340,7 +339,7 @@@ static void handle_internal_command(in
                { "receive-pack", cmd_receive_pack },
                { "reflog", cmd_reflog, RUN_SETUP },
                { "remote", cmd_remote, RUN_SETUP },
+               { "replace", cmd_replace, RUN_SETUP },
                { "repo-config", cmd_config },
                { "rerere", cmd_rerere, RUN_SETUP },
                { "reset", cmd_reset, RUN_SETUP },
@@@ -416,9 -418,13 +417,9 @@@ static void execv_dashed_external(cons
         * if we fail because the command is not found, it is
         * OK to return. Otherwise, we just pass along the status code.
         */
 -      status = run_command_v_opt(argv, 0);
 -      if (status != -ERR_RUN_COMMAND_EXEC) {
 -              if (IS_RUN_COMMAND_ERR(status))
 -                      die("unable to run '%s'", argv[0]);
 -              exit(-status);
 -      }
 -      errno = ENOENT; /* as if we called execvp */
 +      status = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE);
 +      if (status >= 0 || errno != ENOENT)
 +              exit(status);
  
        argv[0] = tmp;
  
diff --combined mktag.c
index a609e3ebd106ed985fa2065dc4af6565e5a379a6,6e0b5feaeef8db05fa1dcc2d54be8f1b0a9dac73..a3b4270c18ea78fa36f7243de5a9e05e2066e030
+++ b/mktag.c
  /*
   * We refuse to tag something we can't verify. Just because.
   */
- static int verify_object(unsigned char *sha1, const char *expected_type)
+ static int verify_object(const unsigned char *sha1, const char *expected_type)
  {
        int ret = -1;
        enum object_type type;
        unsigned long size;
-       void *buffer = read_sha1_file(sha1, &type, &size);
+       const unsigned char *repl;
+       void *buffer = read_sha1_file_repl(sha1, &type, &size, &repl);
  
        if (buffer) {
                if (type == type_from_string(expected_type))
-                       ret = check_sha1_signature(sha1, buffer, size, expected_type);
+                       ret = check_sha1_signature(repl, buffer, size, expected_type);
                free(buffer);
        }
        return ret;
@@@ -165,7 -166,7 +166,7 @@@ int main(int argc, char **argv
        setup_git_directory();
  
        if (strbuf_read(&buf, 0, 4096) < 0) {
 -              die("could not read from stdin");
 +              die_errno("could not read from stdin");
        }
  
        /* Verify it for some basic sanity: it needs to start with
diff --combined parse-options.c
index 3b71fbb5410332a3f11ca0e450a614b3345a687b,743f5bae4e11346d37038faba08219275addc334..a64a4d6ee267cf2a691f546f668f3f644616408c
@@@ -306,28 -306,6 +306,28 @@@ static void check_typos(const char *arg
        }
  }
  
 +static void parse_options_check(const struct option *opts)
 +{
 +      int err = 0;
 +
 +      for (; opts->type != OPTION_END; opts++) {
 +              if ((opts->flags & PARSE_OPT_LASTARG_DEFAULT) &&
 +                  (opts->flags & PARSE_OPT_OPTARG)) {
 +                      if (opts->long_name) {
 +                              error("`--%s` uses incompatible flags "
 +                                    "LASTARG_DEFAULT and OPTARG", opts->long_name);
 +                      } else {
 +                              error("`-%c` uses incompatible flags "
 +                                    "LASTARG_DEFAULT and OPTARG", opts->short_name);
 +                      }
 +                      err |= 1;
 +              }
 +      }
 +
 +      if (err)
 +              exit(129);
 +}
 +
  void parse_options_start(struct parse_opt_ctx_t *ctx,
                         int argc, const char **argv, const char *prefix,
                         int flags)
@@@ -353,8 -331,6 +353,8 @@@ int parse_options_step(struct parse_opt
  {
        int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
  
 +      parse_options_check(options);
 +
        /* we must reset ->opt, unknown short option leave it dangling */
        ctx->opt = NULL;
  
@@@ -464,7 -440,7 +464,7 @@@ int parse_options(int argc, const char 
  static int usage_argh(const struct option *opts)
  {
        const char *s;
 -      int literal = opts->flags & PARSE_OPT_LITERAL_ARGHELP;
 +      int literal = (opts->flags & PARSE_OPT_LITERAL_ARGHELP) || !opts->argh;
        if (opts->flags & PARSE_OPT_OPTARG)
                if (opts->long_name)
                        s = literal ? "[=%s]" : "[=<%s>]";
                        s = literal ? "[%s]" : "[<%s>]";
        else
                s = literal ? " %s" : " <%s>";
 -      return fprintf(stderr, s, opts->argh);
 +      return fprintf(stderr, s, opts->argh ? opts->argh : "...");
  }
  
  #define USAGE_OPTS_WIDTH 24
  #define USAGE_GAP         2
  
 -int usage_with_options_internal(const char * const *usagestr,
 +static int usage_with_options_internal(const char * const *usagestr,
                                const struct option *opts, int full)
  {
        if (!usagestr)
                        continue;
  
                pos = fprintf(stderr, "    ");
 -              if (opts->short_name) {
 +              if (opts->short_name && !(opts->flags & PARSE_OPT_NEGHELP)) {
                        if (opts->flags & PARSE_OPT_NODASH)
                                pos += fprintf(stderr, "%c", opts->short_name);
                        else
                if (opts->long_name && opts->short_name)
                        pos += fprintf(stderr, ", ");
                if (opts->long_name)
 -                      pos += fprintf(stderr, "--%s", opts->long_name);
 +                      pos += fprintf(stderr, "--%s%s",
 +                              (opts->flags & PARSE_OPT_NEGHELP) ?  "no-" : "",
 +                              opts->long_name);
                if (opts->type == OPTION_NUMBER)
                        pos += fprintf(stderr, "-NUM");
  
 -              switch (opts->type) {
 -              case OPTION_ARGUMENT:
 -                      break;
 -              case OPTION_INTEGER:
 -                      if (opts->flags & PARSE_OPT_OPTARG)
 -                              if (opts->long_name)
 -                                      pos += fprintf(stderr, "[=<n>]");
 -                              else
 -                                      pos += fprintf(stderr, "[<n>]");
 -                      else
 -                              pos += fprintf(stderr, " <n>");
 -                      break;
 -              case OPTION_CALLBACK:
 -                      if (opts->flags & PARSE_OPT_NOARG)
 -                              break;
 -                      /* FALLTHROUGH */
 -              case OPTION_FILENAME:
 -                      /* FALLTHROUGH */
 -              case OPTION_STRING:
 -                      if (opts->argh)
 -                              pos += usage_argh(opts);
 -                      else {
 -                              if (opts->flags & PARSE_OPT_OPTARG)
 -                                      if (opts->long_name)
 -                                              pos += fprintf(stderr, "[=...]");
 -                                      else
 -                                              pos += fprintf(stderr, "[...]");
 -                              else
 -                                      pos += fprintf(stderr, " ...");
 -                      }
 -                      break;
 -              default: /* OPTION_{BIT,BOOLEAN,NUMBER,SET_INT,SET_PTR} */
 -                      break;
 -              }
 +              if (!(opts->flags & PARSE_OPT_NOARG))
 +                      pos += usage_argh(opts);
  
                if (pos <= USAGE_OPTS_WIDTH)
                        pad = USAGE_OPTS_WIDTH - pos;
@@@ -549,6 -555,14 +549,14 @@@ void usage_with_options(const char * co
        exit(129);
  }
  
+ void usage_msg_opt(const char *msg,
+                  const char * const *usagestr,
+                  const struct option *options)
+ {
+       fprintf(stderr, "%s\n\n", msg);
+       usage_with_options(usagestr, options);
+ }
  int parse_options_usage(const char * const *usagestr,
                        const struct option *opts)
  {
diff --combined parse-options.h
index b32587ad7cbf5ac3923764d68d1ccd197955e660,f0f885c67de0905d80e414ce3c4b0aa83d3c813c..f295a2cf858f4dbebc62e956878544ffdb7fbe58
@@@ -36,7 -36,6 +36,7 @@@ enum parse_opt_option_flags 
        PARSE_OPT_LASTARG_DEFAULT = 16,
        PARSE_OPT_NODASH = 32,
        PARSE_OPT_LITERAL_ARGHELP = 64,
 +      PARSE_OPT_NEGHELP = 128,
  };
  
  struct option;
@@@ -68,22 -67,16 +68,22 @@@ typedef int parse_opt_cb(const struct o
   * `flags`::
   *   mask of parse_opt_option_flags.
   *   PARSE_OPT_OPTARG: says that the argument is optional (not for BOOLEANs)
 - *   PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
 + *   PARSE_OPT_NOARG: says that this option takes no argument
   *   PARSE_OPT_NONEG: says that this option cannot be negated
   *   PARSE_OPT_HIDDEN: this option is skipped in the default usage, and
   *                     shown only in the full usage.
 - *   PARSE_OPT_LASTARG_DEFAULT: if no argument is given, the default value
 - *                              is used.
 + *   PARSE_OPT_LASTARG_DEFAULT: says that this option will take the default
 + *                            value if no argument is given when the option
 + *                            is last on the command line. If the option is
 + *                            not last it will require an argument.
 + *                            Should not be used with PARSE_OPT_OPTARG.
   *   PARSE_OPT_NODASH: this option doesn't start with a dash.
   *   PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
   *                            (i.e. '<argh>') in the help message.
   *                            Useful for options with multiple parameters.
 + *   PARSE_OPT_NEGHELP: says that the long option should always be shown with
 + *                            the --no prefix in the usage message. Sometimes
 + *                            useful for users of OPTION_NEGBIT.
   *
   * `callback`::
   *   pointer to the callback to use for OPTION_CALLBACK.
@@@ -108,20 -101,14 +108,20 @@@ struct option 
  };
  
  #define OPT_END()                   { OPTION_END }
 -#define OPT_ARGUMENT(l, h)          { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
 +#define OPT_ARGUMENT(l, h)          { OPTION_ARGUMENT, 0, (l), NULL, NULL, \
 +                                    (h), PARSE_OPT_NOARG}
  #define OPT_GROUP(h)                { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
 -#define OPT_BIT(s, l, v, h, b)      { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
 -#define OPT_NEGBIT(s, l, v, h, b)   { OPTION_NEGBIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
 -#define OPT_BOOLEAN(s, l, v, h)     { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
 -#define OPT_SET_INT(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) }
 -#define OPT_SET_PTR(s, l, v, h, p)  { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) }
 -#define OPT_INTEGER(s, l, v, h)     { OPTION_INTEGER, (s), (l), (v), NULL, (h) }
 +#define OPT_BIT(s, l, v, h, b)      { OPTION_BIT, (s), (l), (v), NULL, (h), \
 +                                    PARSE_OPT_NOARG, NULL, (b) }
 +#define OPT_NEGBIT(s, l, v, h, b)   { OPTION_NEGBIT, (s), (l), (v), NULL, \
 +                                    (h), PARSE_OPT_NOARG, NULL, (b) }
 +#define OPT_BOOLEAN(s, l, v, h)     { OPTION_BOOLEAN, (s), (l), (v), NULL, \
 +                                    (h), PARSE_OPT_NOARG }
 +#define OPT_SET_INT(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, \
 +                                    (h), PARSE_OPT_NOARG, NULL, (i) }
 +#define OPT_SET_PTR(s, l, v, h, p)  { OPTION_SET_PTR, (s), (l), (v), NULL, \
 +                                    (h), PARSE_OPT_NOARG, NULL, (p) }
 +#define OPT_INTEGER(s, l, v, h)     { OPTION_INTEGER, (s), (l), (v), "n", (h) }
  #define OPT_STRING(s, l, v, a, h)   { OPTION_STRING,  (s), (l), (v), (a), (h) }
  #define OPT_DATE(s, l, v, h) \
        { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \
@@@ -145,6 -132,10 +145,10 @@@ extern int parse_options(int argc, cons
  extern NORETURN void usage_with_options(const char * const *usagestr,
                                          const struct option *options);
  
+ extern NORETURN void usage_msg_opt(const char *msg,
+                                  const char * const *usagestr,
+                                  const struct option *options);
  /*----- incremental advanced APIs -----*/
  
  enum {
diff --combined refs.c
index dd9c9ba3f6cb1b7e742adaee89cc406c44d77367,6a136512c716c2169aed82107d077aad5142095c..24865cf5a6c937834b2a98ccd8d80a652ae5541e
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -531,10 -531,9 +531,10 @@@ static int do_one_ref(const char *base
  {
        if (strncmp(base, entry->name, trim))
                return 0;
 +      /* Is this a "negative ref" that represents a deleted ref? */
 +      if (is_null_sha1(entry->sha1))
 +              return 0;
        if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
 -              if (is_null_sha1(entry->sha1))
 -                      return 0;
                if (!has_sha1_file(entry->sha1)) {
                        error("%s does not point to a valid object!", entry->name);
                        return 0;
@@@ -668,6 -667,11 +668,11 @@@ int for_each_remote_ref(each_ref_fn fn
        return for_each_ref_in("refs/remotes/", fn, cb_data);
  }
  
+ int for_each_replace_ref(each_ref_fn fn, void *cb_data)
+ {
+       return do_for_each_ref("refs/replace/", fn, 13, 0, cb_data);
+ }
  int for_each_rawref(each_ref_fn fn, void *cb_data)
  {
        return do_for_each_ref("refs/", fn, 0,
@@@ -821,7 -825,7 +826,7 @@@ static int remove_empty_directories(con
        strbuf_init(&path, 20);
        strbuf_addstr(&path, file);
  
 -      result = remove_dir_recursively(&path, 1);
 +      result = remove_dir_recursively(&path, REMOVE_DIR_EMPTY_ONLY);
  
        strbuf_release(&path);
  
@@@ -1419,7 -1423,7 +1424,7 @@@ int read_ref_at(const char *ref, unsign
        logfile = git_path("logs/%s", ref);
        logfd = open(logfile, O_RDONLY, 0);
        if (logfd < 0)
 -              die("Unable to read log %s: %s", logfile, strerror(errno));
 +              die_errno("Unable to read log '%s'", logfile);
        fstat(logfd, &st);
        if (!st.st_size)
                die("Log %s is empty.", logfile);
@@@ -1526,10 -1530,8 +1531,10 @@@ int for_each_recent_reflog_ent(const ch
                if (fstat(fileno(logfp), &statbuf) ||
                    statbuf.st_size < ofs ||
                    fseek(logfp, -ofs, SEEK_END) ||
 -                  fgets(buf, sizeof(buf), logfp))
 +                  fgets(buf, sizeof(buf), logfp)) {
 +                      fclose(logfp);
                        return -1;
 +              }
        }
  
        while (fgets(buf, sizeof(buf), logfp)) {
diff --combined sha1_file.c
index 1d996a199036c115d46c1d630d53edf29b3b78e7,9119b795bd2c39d91731f181a304e9575c0564f5..4ea0b18d0aaeca48ed75ed21863195c5ce830cbc
@@@ -1162,7 -1162,8 +1162,7 @@@ unsigned long unpack_object_header_buff
                unsigned long len, enum object_type *type, unsigned long *sizep)
  {
        unsigned shift;
 -      unsigned char c;
 -      unsigned long size;
 +      unsigned long size, c;
        unsigned long used = 0;
  
        c = buf[used++];
        size = c & 15;
        shift = 4;
        while (c & 0x80) {
 -              if (len <= used || sizeof(long) * 8 <= shift) {
 +              if (len <= used || bitsizeof(long) <= shift) {
                        error("bad object header");
                        return 0;
                }
@@@ -2144,13 -2145,26 +2144,26 @@@ static void *read_object(const unsigne
        return read_packed_sha1(sha1, type, size);
  }
  
- void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
-                    unsigned long *size)
+ void *read_sha1_file_repl(const unsigned char *sha1,
+                         enum object_type *type,
+                         unsigned long *size,
+                         const unsigned char **replacement)
  {
-       void *data = read_object(sha1, type, size);
+       const unsigned char *repl = lookup_replace_object(sha1);
+       void *data = read_object(repl, type, size);
+       /* die if we replaced an object with one that does not exist */
+       if (!data && repl != sha1)
+               die("replacement %s not found for %s",
+                   sha1_to_hex(repl), sha1_to_hex(sha1));
        /* legacy behavior is to die on corrupted objects */
-       if (!data && (has_loose_object(sha1) || has_packed_and_bad(sha1)))
-               die("object %s is corrupted", sha1_to_hex(sha1));
+       if (!data && (has_loose_object(repl) || has_packed_and_bad(repl)))
+               die("object %s is corrupted", sha1_to_hex(repl));
+       if (replacement)
+               *replacement = repl;
        return data;
  }
  
@@@ -2286,7 -2300,7 +2299,7 @@@ static void close_sha1_file(int fd
        if (fsync_object_files)
                fsync_or_die(fd, "sha1 file");
        if (close(fd) != 0)
 -              die("error when closing sha1 file (%s)", strerror(errno));
 +              die_errno("error when closing sha1 file");
  }
  
  /* Size of directory component, including the ending '/' */
diff --combined upload-pack.c
index f7d308a411d22cf350a6ac4512ee2ebb195f87d7,e6c4f347ebf4bbee3bf6826c8089ad81cac15ed6..4d8be834ff45ba869bb84f0fa8a424a3c469a200
@@@ -28,8 -28,7 +28,8 @@@ static unsigned long oldest_have
  
  static int multi_ack, nr_our_refs;
  static int use_thin_pack, use_ofs_delta, use_include_tag;
 -static int no_progress;
 +static int no_progress, daemon_mode;
 +static int shallow_nr;
  static struct object_array have_obj;
  static struct object_array want_obj;
  static unsigned int timeout;
@@@ -108,6 -107,8 +108,6 @@@ static int do_rev_list(int fd, void *cr
        struct rev_info revs;
  
        pack_pipe = fdopen(fd, "w");
 -      if (create_full_pack)
 -              use_thin_pack = 0; /* no point doing it */
        init_revisions(&revs, NULL);
        revs.tag_objects = 1;
        revs.tree_objects = 1;
@@@ -154,21 -155,13 +154,21 @@@ static void create_pack_file(void
        const char *argv[10];
        int arg = 0;
  
 -      rev_list.proc = do_rev_list;
 -      /* .data is just a boolean: any non-NULL value will do */
 -      rev_list.data = create_full_pack ? &rev_list : NULL;
 -      if (start_async(&rev_list))
 -              die("git upload-pack: unable to fork git-rev-list");
 +      if (shallow_nr) {
 +              rev_list.proc = do_rev_list;
 +              rev_list.data = 0;
 +              if (start_async(&rev_list))
 +                      die("git upload-pack: unable to fork git-rev-list");
 +              argv[arg++] = "pack-objects";
 +      } else {
 +              argv[arg++] = "pack-objects";
 +              argv[arg++] = "--revs";
 +              if (create_full_pack)
 +                      argv[arg++] = "--all";
 +              else if (use_thin_pack)
 +                      argv[arg++] = "--thin";
 +      }
  
 -      argv[arg++] = "pack-objects";
        argv[arg++] = "--stdout";
        if (!no_progress)
                argv[arg++] = "--progress";
        argv[arg++] = NULL;
  
        memset(&pack_objects, 0, sizeof(pack_objects));
 -      pack_objects.in = rev_list.out; /* start_command closes it */
 +      pack_objects.in = shallow_nr ? rev_list.out : -1;
        pack_objects.out = -1;
        pack_objects.err = -1;
        pack_objects.git_cmd = 1;
        if (start_command(&pack_objects))
                die("git upload-pack: unable to fork git-pack-objects");
  
 +      /* pass on revisions we (don't) want */
 +      if (!shallow_nr) {
 +              FILE *pipe_fd = fdopen(pack_objects.in, "w");
 +              if (!create_full_pack) {
 +                      int i;
 +                      for (i = 0; i < want_obj.nr; i++)
 +                              fprintf(pipe_fd, "%s\n", sha1_to_hex(want_obj.objects[i].item->sha1));
 +                      fprintf(pipe_fd, "--not\n");
 +                      for (i = 0; i < have_obj.nr; i++)
 +                              fprintf(pipe_fd, "%s\n", sha1_to_hex(have_obj.objects[i].item->sha1));
 +              }
 +
 +              fprintf(pipe_fd, "\n");
 +              fflush(pipe_fd);
 +              fclose(pipe_fd);
 +      }
 +
 +
        /* We read from pack_objects.err to capture stderr output for
         * progress bar, and pack_objects.out to capture the pack data.
         */
                error("git upload-pack: git-pack-objects died with error.");
                goto fail;
        }
 -      if (finish_async(&rev_list))
 +      if (shallow_nr && finish_async(&rev_list))
                goto fail;      /* error was already reported */
  
        /* flush the data */
@@@ -476,7 -451,6 +476,7 @@@ static void receive_needs(void
        static char line[1000];
        int len, depth = 0;
  
 +      shallow_nr = 0;
        if (debug_fd)
                write_in_full(debug_fd, "#S\n", 3);
        for (;;) {
        }
        if (debug_fd)
                write_in_full(debug_fd, "#E\n", 3);
 +
 +      if (!use_sideband && daemon_mode)
 +              no_progress = 1;
 +
        if (depth == 0 && shallows.nr == 0)
                return;
        if (depth > 0) {
                                packet_write(1, "shallow %s",
                                                sha1_to_hex(object->sha1));
                                register_shallow(object->sha1);
 +                              shallow_nr++;
                        }
                        result = result->next;
                }
                        for (i = 0; i < shallows.nr; i++)
                                register_shallow(shallows.objects[i].item->sha1);
                }
 +
 +      shallow_nr += shallows.nr;
        free(shallows.objects);
  }
  
@@@ -651,6 -618,7 +651,7 @@@ int main(int argc, char **argv
        int strict = 0;
  
        git_extract_argv0_path(argv[0]);
+       read_replace_refs = 0;
  
        for (i = 1; i < argc; i++) {
                char *arg = argv[i];
                }
                if (!prefixcmp(arg, "--timeout=")) {
                        timeout = atoi(arg+10);
 +                      daemon_mode = 1;
                        continue;
                }
                if (!strcmp(arg, "--")) {