Code

Merge refs/heads/portable from http://www.cs.berkeley.edu/~ejr/gits/git.git
authorJunio C Hamano <junkio@cox.net>
Mon, 29 Aug 2005 06:02:01 +0000 (23:02 -0700)
committerJunio C Hamano <junkio@cox.net>
Mon, 29 Aug 2005 06:02:01 +0000 (23:02 -0700)
74 files changed:
.gitignore [new file with mode: 0644]
Documentation/.gitignore [new file with mode: 0644]
Documentation/Makefile
Documentation/SubmittingPatches
Documentation/git-add-script.txt
Documentation/git-branch-script.txt
Documentation/git-cherry.txt
Documentation/git-count-objects-script.txt
Documentation/git-fetch-script.txt
Documentation/git-mailsplit.txt
Documentation/git-octopus-script.txt [new file with mode: 0644]
Documentation/git-patch-id.txt
Documentation/git-pull-script.txt
Documentation/git-push-script.txt
Documentation/git-rebase-script.txt
Documentation/git-relink-script.txt
Documentation/git-resolve-script.txt
Documentation/git-revert-script.txt
Documentation/git-send-pack.txt
Documentation/git-sh-setup-script.txt
Documentation/git-stripspace.txt
Documentation/git-verify-tag-script.txt
Documentation/git.txt
Documentation/glossary.txt
Documentation/howto-index.sh [new file with mode: 0755]
Documentation/howto/make-dist.txt
Documentation/howto/rebase-and-edit.txt
Documentation/howto/rebase-from-internal-branch.txt
Documentation/howto/rebuild-from-update-hook.txt [new file with mode: 0644]
Documentation/howto/using-topic-branches.txt
Documentation/install-webdoc.sh [new file with mode: 0755]
Documentation/pull-fetch-param.txt
Documentation/tutorial.txt
Makefile
apply.c
cache.h
connect.c
debian/.gitignore [new file with mode: 0644]
debian/changelog
debian/control
debian/git-core.doc-base
debian/git-tk.files
debian/rules
git-bisect-script
git-branch-script
git-checkout-script
git-clone-script
git-commit-script
git-fetch-script
git-log-script
git-ls-remote-script
git-octopus-script [new file with mode: 0755]
git-parse-remote [deleted file]
git-parse-remote-script [new file with mode: 0755]
git-pull-script
git-push-script
git-repack-script
git-request-pull-script
git-resolve-script
git-revert-script
git-sh-setup-script
git-status-script
ls-files.c
merge-base.c
rev-list.c
rev-parse.c
send-pack.c
setup.c
show-branch.c
t/t4109-apply-multifrag.sh [new file with mode: 0644]
t/t4110-apply-scan.sh [new file with mode: 0644]
templates/.gitignore [new file with mode: 0644]
templates/remotes-- [new file with mode: 0644]
tools/.gitignore [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..245f54e
--- /dev/null
@@ -0,0 +1,51 @@
+git-apply
+git-build-rev-cache
+git-cat-file
+git-checkout-cache
+git-clone-pack
+git-commit-tree
+git-convert-cache
+git-daemon
+git-diff-cache
+git-diff-files
+git-diff-helper
+git-diff-stages
+git-diff-tree
+git-export
+git-fetch-pack
+git-fsck-cache
+git-get-tar-commit-id
+git-hash-object
+git-http-pull
+git-init-db
+git-local-pull
+git-ls-files
+git-ls-tree
+git-merge-base
+git-merge-cache
+git-mktag
+git-pack-objects
+git-patch-id
+git-peek-remote
+git-prune-packed
+git-read-tree
+git-receive-pack
+git-rev-list
+git-rev-parse
+git-rev-tree
+git-send-pack
+git-show-branch
+git-show-index
+git-show-rev-cache
+git-ssh-pull
+git-ssh-push
+git-stripspace
+git-tar-tree
+git-unpack-file
+git-unpack-objects
+git-update-cache
+git-update-server-info
+git-upload-pack
+git-var
+git-verify-pack
+git-write-tree
diff --git a/Documentation/.gitignore b/Documentation/.gitignore
new file mode 100644 (file)
index 0000000..dad52b8
--- /dev/null
@@ -0,0 +1,5 @@
+*.xml
+*.html
+*.1
+*.7
+howto-index.txt
index 91addedca0cee764a74723272f4953dd70a1b62d..bd6833b79ef1354c05062fb063d335dcb6bb8511 100644 (file)
@@ -1,9 +1,10 @@
-MAN1_TXT=$(wildcard git-*.txt)
+MAN1_TXT=$(wildcard git-*.txt) gitk.txt
 MAN7_TXT=git.txt
 
 DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT))
 DOC_HTML += glossary.html
 DOC_HTML += tutorial.html
+DOC_HTML += howto-index.html
 DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT))
 DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
 
@@ -44,7 +45,7 @@ git-diff-%.txt: diff-format.txt diff-options.txt
        touch $@
 
 clean:
-       rm -f *.xml *.html *.1 *.7
+       rm -f *.xml *.html *.1 *.7 howto-index.txt
 
 %.html : %.txt
        asciidoc -b xhtml11 -d manpage $<
@@ -62,3 +63,16 @@ glossary.html : glossary.txt sort_glossary.pl
 
 tutorial.html : tutorial.txt
        asciidoc -b xhtml11 tutorial.txt
+
+howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
+       rm -f $@+ $@
+       sh ./howto-index.sh $(wildcard howto/*.txt) >$@+
+       mv $@+ $@
+
+howto-index.html: howto-index.txt
+       asciidoc -b xhtml11 howto-index.txt
+
+WEBDOC_DEST = /pub/software/scm/git/docs
+
+install-webdoc : html
+       sh ./install-webdoc.sh $(WEBDOC_DEST)
index 6121e902ae206c95fb4503918ec91b452977442d..fd9881f26c09c08a76acea8c30d4cedbc9bcedea 100644 (file)
@@ -73,14 +73,25 @@ MIME-attached change being accepted, but it makes it more likely
 that it will be postponed.
 
 Exception:  If your mailer is mangling patches then someone may ask
-you to re-send them using MIME.
+you to re-send them using MIME, that is OK.
 
-Note that your maintainer does not subscribe to the git mailing
-list (he reads it via mail-to-news gateway).  If your patch is
-for discussion first, send it "To:" the mailing list, and
-optoinally "cc:" him.  If it is trivially correct or after list
-discussion reached consensus, send it "To:" the maintainer and
-optionally "cc:" the list.
+Do not PGP sign your patch, at least for now.  Most likely, your
+maintainer or other people on the list would not have your PGP
+key and would not bother obtaining it anyway.  Your patch is not
+judged by who you are; a good patch from an unknown origin has a
+far better chance of being accepted than a patch from a known,
+respected origin that is done poorly or does incorrect things.
+
+If you really really really really want to do a PGP signed
+patch, format it as "multipart/signed", not a text/plain message
+that starts with '-----BEGIN PGP SIGNED MESSAGE-----'.  That is
+not a text/plain, it's something else.
+
+Note that your maintainer does not necessarily read everything
+on the git mailing list.  If your patch is for discussion first,
+send it "To:" the mailing list, and optionally "cc:" him.  If it
+is trivially correct or after the list reached a consensus, send
+it "To:" the maintainer and optionally "cc:" the list.
 
 
 (6) Sign your work
@@ -128,3 +139,152 @@ then you just add a line saying
 Some people also put extra tags at the end.  They'll just be ignored for
 now, but you can do this to mark internal company procedures or just
 point out some special detail about the sign-off.
+
+
+------------------------------------------------
+MUA specific hints
+
+Some of patches I receive or pick up from the list share common
+patterns of breakage.  Please make sure your MUA is set up
+properly not to corrupt whitespaces.  Here are two common ones
+I have seen:
+
+* Empty context lines that do not have _any_ whitespace.
+
+* Non empty context lines that have one extra whitespace at the
+  beginning.
+
+One test you could do yourself if your MUA is set up correctly is:
+
+* Send the patch to yourself, exactly the way you would, except
+  To: and Cc: lines, which would not contain the list and
+  maintainer address.
+
+* Save that patch to a file in UNIX mailbox format.  Call it say
+  a.patch.
+
+* Try to apply to the tip of the "master" branch from the
+  git.git public repository:
+
+    $ git fetch http://kernel.org/pub/scm/git/git.git master:test-apply
+    $ git checkout test-apply
+    $ git reset --hard
+    $ git applymbox a.patch
+
+If it does not apply correctly, there can be various reasons.
+
+* Your patch itself does not apply cleanly.  That is _bad_ but
+  does not have much to do with your MUA.  Please rebase the
+  patch appropriately.
+
+* Your MUA corrupted your patch; applymbox would complain that
+  the patch does not apply.  Look at .dotest/ subdirectory and
+  see what 'patch' file contains and check for the common
+  corruption patterns mentioned above.
+
+* While you are at it, check what are in 'info' and
+  'final-commit' files as well.  If what is in 'final-commit' is
+  not exactly what you would want to see in the commit log
+  message, it is very likely that your maintainer would end up
+  hand editing the log message when he applies your patch.
+  Things like "Hi, this is my first patch.\n", if you really
+  want to put in the patch e-mail, should come after the
+  three-dash line that signals the end of the commit message.
+
+
+Pine
+----
+
+(Johannes Schindelin)
+
+I don't know how many people still use pine, but for those poor
+souls it may be good to mention that the quell-flowed-text is
+needed for recent versions.
+
+... the "no-strip-whitespace-before-send" option, too. AFAIK it
+was introduced in 4.60.
+
+(Linus Torvalds)
+
+And 4.58 needs at least this.
+
+---
+diff-tree 8326dd8350be64ac7fc805f6563a1d61ad10d32c (from e886a61f76edf5410573e92e38ce22974f9c40f1)
+Author: Linus Torvalds <torvalds@g5.osdl.org>
+Date:   Mon Aug 15 17:23:51 2005 -0700
+
+    Fix pine whitespace-corruption bug
+
+    There's no excuse for unconditionally removing whitespace from
+    the pico buffers on close.
+
+diff --git a/pico/pico.c b/pico/pico.c
+--- a/pico/pico.c
++++ b/pico/pico.c
+@@ -219,7 +219,9 @@ PICO *pm;
+           switch(pico_all_done){      /* prepare for/handle final events */
+             case COMP_EXIT :          /* already confirmed */
+               packheader();
++#if 0
+               stripwhitespace();
++#endif
+               c |= COMP_EXIT;
+               break;
+
+
+Thunderbird
+-----------
+
+(A Large Angry SCM)
+
+Here are some hints on how to successfully submit patches inline using
+Thunderbird. [*3*]
+
+This recipe appears to work with the current [*1*] Thunderbird from Suse.
+
+The following Thunderbird extensions are needed:
+       AboutConfig 0.5
+               http://aboutconfig.mozdev.org/
+       External Editor 0.5.4
+               http://extensionroom.mozdev.org/more-info/exteditor
+
+1) Prepare the patch as a text file using your method of choice.
+
+2) Before opening a compose window, use Edit->Account Settings to
+uncheck the "Compose messages in HTML format" setting in the
+"Composition & Addressing" panel of the account to be used to send the
+patch. [*2*]
+
+3) In the main Thunderbird window, _before_ you open the compose window
+for the patch, use Tools->about:config to set the following to the
+indicated values:
+       mailnews.send_plaintext_flowed  => false
+       mailnews.wraplength             => 999
+
+4) Open a compose window and click the external editor icon.
+
+5) In the external editor window, read in the patch file and exit the
+editor normally.
+
+6) Back in the compose window: Add whatever other text you wish to the
+message, complete the addressing and subject fields, and press send.
+
+7) Optionally, undo the about:config/account settings changes made in
+steps 2 & 3.
+
+
+[Footnotes]
+*1* Version 1.0 (20041207) from the MozillaThunderbird-1.0-5 rpm of Suse
+9.3 professional updates.
+
+*2* It may be possible to do this with about:config and the following
+settings but I haven't tried, yet.
+       mail.html_compose                       => false
+       mail.identity.default.compose_html      => false
+       mail.identity.id?.compose_html          => false
+
+*3* Even after following these hints, Thunderbird will still trim
+trailing whitespace from each line. I currently have no work around for
+for this issue.
+
index 866d9c2d943d3c6af79ae0363ee31fb7b0af944c..300114358a2a765919c3720492329136ca82ff0e 100644 (file)
@@ -3,26 +3,21 @@ git-add-script(1)
 
 NAME
 ----
-git-add-script - Some git command not yet documented.
-
+git-add-script - Add files to the cache.
 
 SYNOPSIS
 --------
-'git-add-script' [ --option ] <args>...
+'git-add-script' <file>...
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
+A simple wrapper to git-update-cache to add files to the cache for people used
+to do "cvs add".
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
-
+<file>...::
+       Files to add to the cache.
 
 Author
 ------
index fe9a041950ef876c8157efbe77327e28759ec57f..3ace8adc8315d518fb2dcaeb72d833dadc7e2ac1 100644 (file)
@@ -3,26 +3,27 @@ git-branch-script(1)
 
 NAME
 ----
-git-branch-script - Some git command not yet documented.
-
+git-branch-script - Create a new branch.
 
 SYNOPSIS
 --------
-'git-branch-script' [ --option ] <args>...
+'git-branch-script' [<branchname> [start-point]]
 
 DESCRIPTION
 -----------
-Does something not yet documented.
+If no argument is provided, show available branches and mark current
+branch with star. Otherwise, create a new branch of name <branchname>.
 
+If a starting point is also specified, that will be where the branch is
+created, otherwise it will be created at the current HEAD.
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
+<branchname>::
+       The name of the branch to create.
 
+start-point::
+       Where to make the branch; defaults to HEAD.
 
 Author
 ------
index 14d0bd51cd6ea23696b8b60d4e804440f408ce1e..9ff7bc25c1e8ccdf8204414536ad4373bd868b89 100644 (file)
@@ -3,26 +3,30 @@ git-cherry(1)
 
 NAME
 ----
-git-cherry - Some git command not yet documented.
-
+git-cherry - Find commits not merged upstream.
 
 SYNOPSIS
 --------
-'git-cherry' [ --option ] <args>...
+'git-cherry' [-v] <upstream> [<head>]
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
+Each commit between the fork-point and <head> is examined, and compared against
+the change each commit between the fork-point and <upstream> introduces.
+Commits already included in upstream are prefixed with '-' (meaning "drop from
+my local pull"), while commits missing from upstream are prefixed with '+'
+(meaning "add to the updated upstream").
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
+-v::
+       Verbose.
 
-<args>...::
-       Some argument not yet documented.
+<upstream>::
+       Upstream branch to compare against.
 
+<head>::
+       Working branch; defaults to HEAD.
 
 Author
 ------
index 254361709428679b60450aaa25f2095d8c2322b9..8a3cedfb5f7281e9f488770ac76d746fdf99cf86 100644 (file)
@@ -3,26 +3,16 @@ git-count-objects-script(1)
 
 NAME
 ----
-git-count-objects-script - Some git command not yet documented.
-
+git-count-objects-script - Reports on unpacked objects.
 
 SYNOPSIS
 --------
-'git-count-objects-script' [ --option ] <args>...
+'git-count-objects-script'
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
-
-OPTIONS
--------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
-
+This counts the number of unpacked object files and disk space consumed by
+them, to help you decide when it is a good time to repack.
 
 Author
 ------
index db3086c7329bdbcad32b81e9f5c7ad23d6cca0b1..d15222b5619fbf0fae24f4aac764b6de0c29817c 100644 (file)
@@ -1,6 +1,6 @@
 git-fetch-script(1)
 ===================
-v0.99.4, Aug 2005
+v0.99.5, Aug 2005
 
 NAME
 ----
@@ -9,24 +9,17 @@ git-fetch-script - Download objects and a head from another repository.
 
 SYNOPSIS
 --------
-'git-fetch-script' <repository> [ <head> | tag <tag> ]
+'git-fetch-script' <repository> <refspec>...
 
 
 DESCRIPTION
 -----------
-Fetches a named head or a tag from another repository, along
-with the objects necessary to complete that head or tag.  The
-head to pull defaults to HEAD if unspecified.  The head or tag
-fetched from the remote repository is stored in
-$GIT_DIR/FETCH_HEAD.
-
-When a <tag> is specified, the <tag> fetched from the remote is
-also copied to the local $GIT_DIR/tags/<tag> file.  When no
-<head> nor <tag> is specified, and <repository> was specified
-with the short-hand notation (i.e. naming a file under the
-$GIT_DIR/branches directory), the head fetched from the remote
-repository is also copied to the local $GIT_DIR/heads/<repository>
-file.
+Fetches named heads or tags from another repository, along with
+the objects necessary to complete them.
+
+The ref names and their object names of fetched refs are stored
+in $GIT_DIR/FETCH_HEAD.  This information is left for a later merge
+operation done by "git resolve" or "git octopus".
 
 
 OPTIONS
index 617276a011584cce6119161afabee5dd64f1a011..789d3a9f1eea744ffe8091200125b33b277489b0 100644 (file)
@@ -3,26 +3,24 @@ git-mailsplit(1)
 
 NAME
 ----
-git-mailsplit - Some git command not yet documented.
-
+git-mailsplit - Totally braindamaged mbox splitter program.
 
 SYNOPSIS
 --------
-'git-mailsplit' [ --option ] <args>...
+'git-mailsplit' <mbox> <directory>
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
+Splits a mbox file into a list of files: "0001" "0002" ..  in the specified
+directory so you can process them further from there.
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
+<mbox>::
+       Mbox file to split.
 
+<directory>::
+       Directory in which to place the individual messages.
 
 Author
 ------
diff --git a/Documentation/git-octopus-script.txt b/Documentation/git-octopus-script.txt
new file mode 100644 (file)
index 0000000..f7a073d
--- /dev/null
@@ -0,0 +1,39 @@
+git-octopus-script(1)
+=====================
+v0.99.5, Aug 2005
+
+NAME
+----
+git-octopus-script - 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 link:git.html[git] suite
+
index 9a4abd124dfd0a6ceea058c3c4105298c81e8f5a..b6fa2a8b399adc80bfa9acbc02c7f5cf5fb88aa6 100644 (file)
@@ -3,26 +3,25 @@ git-patch-id(1)
 
 NAME
 ----
-git-patch-id - Some git command not yet documented.
-
+git-patch-id - Generate a patch ID.
 
 SYNOPSIS
 --------
-'git-patch-id' [ --option ] <args>...
+'git-patch-id' < <patch>
 
 DESCRIPTION
 -----------
-Does something not yet documented.
+A "patch ID" is nothing but a SHA1 of the diff associated with a patch, with
+whitespace and line numbers ignored.  As such, it's "reasonably stable", but at
+the same time also reasonably unique, ie two patches that have the same "patch
+ID" are almost guaranteed to be the same thing.
 
+IOW, you can use this thing to look for likely duplicate commits.
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
-
+<patch>::
+       The diff to create the ID of.
 
 Author
 ------
index ad9d3ab31534ab2f71bb791eb96970c7048ac843..8111813b857ff0a18bd02ab72c407c5a937dccc7 100644 (file)
@@ -9,13 +9,16 @@ git-pull-script - Pull and merge from another repository.
 
 SYNOPSIS
 --------
-'git-pull-script' <repository> [ <head> | tag <tag> ]
+'git-pull-script' <repository> <refspec>...
 
 
 DESCRIPTION
 -----------
-Runs 'git-fetch-script' with the given parameters, then
-'git-resolve-script' to merge the local HEAD and FETCH_HEAD.
+Runs 'git-fetch-script' with the given parameters.
+
+When only one ref is downloaded, runs 'git resolve' to merge it
+into the local HEAD.  Otherwise uses 'git octopus' to merge them
+into the local HEAD.
 
 
 OPTIONS
index 3c1208d5a24a5c493ecd85382d13a8a860d70331..556682f991d612ca3a277e640c0f8d6d2e205c49 100644 (file)
@@ -3,25 +3,23 @@ git-push-script(1)
 
 NAME
 ----
-git-push-script - Some git command not yet documented.
+git-push-script - Update remote refs along with associated objects.
 
 
 SYNOPSIS
 --------
-'git-push-script' [ --option ] <args>...
+'git-push-script' [--all] [--force] <repository> <refspec>...
 
 DESCRIPTION
 -----------
-Does something not yet documented.
+
+Updates remote refs using local refs, while sending objects
+necessary to complete the given refs.
 
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
+include::pull-fetch-param.txt[]
 
 
 Author
index ba7cbb777c5ef5ca8c04337cb1cda55552f5885e..8f14186f82b16fefe64c3f1789bad4e936dfd4eb 100644 (file)
@@ -3,26 +3,23 @@ git-rebase-script(1)
 
 NAME
 ----
-git-rebase-script - Some git command not yet documented.
-
+git-rebase-script - Rebase local commits to new upstream head.
 
 SYNOPSIS
 --------
-'git-rebase-script' [ --option ] <args>...
+'git-rebase-script' <upstream> [<head>]
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
+Rebases local commits to the new head of the upstream tree.
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
+<upstream>::
+       Upstream branch to compare against.
 
+<head>::
+       Working branch; defaults to HEAD.
 
 Author
 ------
index 4c2b435d1e1afc037245284cc803e32e52508449..99c05d45124f7f5293ca778f56c6d611e1440252 100644 (file)
@@ -3,26 +3,25 @@ git-relink-script(1)
 
 NAME
 ----
-git-relink-script - Some git command not yet documented.
-
+git-relink-script - Hardlink common objects in local repositories.
 
 SYNOPSIS
 --------
-'git-relink-script' [ --option ] <args>...
+'git-relink-script' [--safe] <dir> <dir> [<dir>]\*
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
+This will scan 2 or more object repositories and look for common objects, check
+if they are hardlinked, and replace one with a hardlink to the other if not.
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
+--safe::
+       Stops if two objects with the same hash exist but have different sizes.
+       Default is to warn and continue.
 
+<dir>::
+       Directories containing a .git/objects/ subdirectory.
 
 Author
 ------
index 99c399a073cd9cd69783312a6930f3fb2cca55f0..77076aa90dea8e7080ccdb5e0b64845018604ac7 100644 (file)
@@ -1,19 +1,25 @@
 git-resolve-script(1)
 =====================
-v0.99.4, Aug 2005
+v0.99.5, Aug 2005
 
 NAME
 ----
-git-resolve-script - Script used to merge two trees
+git-resolve-script - Merge two commits
 
 
 SYNOPSIS
 --------
-'git-resolve-script'
+'git resolve' <current> <merged> <message>
 
 DESCRIPTION
 -----------
-This script is used by Linus to merge two trees.
+Given two commits and a merge message, merge the <merged> commit
+into <current> commit, with the commit log message <message>.
+
+When <current> is a descendant of <merged>, or <current> is an
+ancestor of <merged>, no new commit is created and the <message>
+is ignored.  The former is informally called "already up to
+date", and the latter is often called "fast forward".
 
 
 Author
index 8a532e6d09306974fb2b8bb32e31e00ed10c0a43..727073e27958cfeaff10c0a4db2fb77b5f2ae73c 100644 (file)
@@ -3,26 +3,22 @@ git-revert-script(1)
 
 NAME
 ----
-git-revert-script - Some git command not yet documented.
-
+git-revert-script - Revert an existing commit.
 
 SYNOPSIS
 --------
-'git-revert-script' [ --option ] <args>...
+'git-revert-script' <commit>
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
+Given one existing commit, revert the change the patch introduces, and record a
+new commit that records it.  This requires your working tree to be clean (no
+modifications from the HEAD commit).
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
-
+<commit>::
+       Commit to revert.
 
 Author
 ------
index 6192c5dc41e57a33afc203fab46940fa4596ba26..5ed25f54d1a68c3cf3c43d7189337106519a1131 100644 (file)
@@ -9,12 +9,12 @@ git-send-pack - Push missing objects packed.
 
 SYNOPSIS
 --------
-'git-send-pack' [--all] [--exec=<git-receive-pack>] [<host>:]<directory> [<head>...]
+'git-send-pack' [--all] [--force] [--exec=<git-receive-pack>] [<host>:]<directory> [<ref>...]
 
 DESCRIPTION
 -----------
 Invokes 'git-receive-pack' on a possibly remote repository, and
-updates it from the current repository, sending named heads.
+updates it from the current repository, sending named refs.
 
 
 OPTIONS
@@ -29,6 +29,13 @@ OPTIONS
        Instead of explicitly specifying which refs to update,
        update all refs that locally exist.
 
+--force::
+       Usually, the command refuses to update a remote ref that
+       is not an ancestor of the local ref used to overwrite it.
+       This flag disables the check.  What this means is that
+       the remote repository can lose commits; use it with
+       care.
+
 <host>::
        A remote host to house the repository.  When this
        part is specified, 'git-receive-pack' is invoked via
@@ -37,7 +44,7 @@ OPTIONS
 <directory>::
        The repository to update.
 
-<head>...:
+<ref>...:
        The remote refs to update.
 
 
@@ -48,24 +55,25 @@ There are three ways to specify which refs to update on the
 remote end.
 
 With '--all' flag, all refs that exist locally are transfered to
-the remote side.  You cannot specify any '<head>' if you use
+the remote side.  You cannot specify any '<ref>' if you use
 this flag.
 
-Without '--all' and without any '<head>', the refs that exist
+Without '--all' and without any '<ref>', the refs that exist
 both on the local side and on the remote side are updated.
 
-When '<head>'s are specified explicitly, it can be either a
+When '<ref>'s are specified explicitly, it can be either a
 single pattern, or a pair of such pattern separated by a colon
 ':' (this means that a ref name cannot have a colon in it).  A
 single pattern '<name>' is just a shorthand for '<name>:<name>'.
+
 Each pattern pair consists of the source side (before the colon)
-and the destination side (after the colon).  The ref that is
+and the destination side (after the colon).  The ref to be
 pushed is determined by finding a match that matches the source
 side, and where it is pushed is determined by using the
 destination side.
 
- - It is an error if <src> does not match exactly one of local
-   refs.
+ - It is an error if <src> does not match exactly one of the
+   local refs.
 
  - It is an error if <dst> matches more than one remote refs.
 
@@ -78,6 +86,17 @@ destination side.
      exist in the set of remote refs; the ref matched <src>
      locally is used as the name of the destination.
 
+Without '--force', the <src> ref is stored at the remote only if
+<dst> does not exist, or <dst> is a proper subset (i.e. an
+ancestor) of <src>.  This check, known as "fast forward check",
+is performed in order to avoid accidentally overwriting the
+remote ref and lose other peoples' commits from there.
+
+With '--force', the fast forward check is disabled for all refs.
+
+Optionally, a <ref> parameter can be prefixed with a plus '+' sign
+to disable the fast-forward check only on that ref.
+
 
 Author
 ------
index 92addd71fec5e938eeafc9be98ebb6609e1802e8..5ac613a2c79999b5db08daa77ef3af574e4efa94 100644 (file)
@@ -3,26 +3,22 @@ git-sh-setup-script(1)
 
 NAME
 ----
-git-sh-setup-script - Some git command not yet documented.
-
+git-sh-setup-script - Common git shell script setup code.
 
 SYNOPSIS
 --------
-'git-sh-setup-script' [ --option ] <args>...
+'git-sh-setup-script'
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
 
-OPTIONS
--------
---option::
-       Some option not yet documented.
+Sets up the normal git environment variables and a few helper functions
+(currently just "die()"), and returns ok if it all looks like a git archive.
+So use it something like
 
-<args>...::
-       Some argument not yet documented.
+       . git-sh-setup-script || die "Not a git archive"
 
+to make the rest of the git scripts more careful and readable.
 
 Author
 ------
index fc87146d594a832051865883f6a47e60ed58585d..d1a550c202adce72adab555a90f98000f2734dee 100644 (file)
@@ -3,26 +3,21 @@ git-stripspace(1)
 
 NAME
 ----
-git-stripspace - Some git command not yet documented.
+git-stripspace - Fileter out empty lines.
 
 
 SYNOPSIS
 --------
-'git-stripspace' [ --option ] <args>...
+'git-stripspace' < <stream>
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
+Remove multiple empty lines, and empty lines at beginning and end.
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
-
+<stream>::
+       Byte stream to act on.
 
 Author
 ------
index 88a264681f7efe23fb30a7eead730403a8ce7ca5..d5d747cd843862a3e2f04dd8357d0c98c75eb702 100644 (file)
@@ -3,26 +3,20 @@ git-verify-tag-script(1)
 
 NAME
 ----
-git-verify-tag-script - Some git command not yet documented.
-
+git-verify-tag-script - Check the GPG signature of tag.
 
 SYNOPSIS
 --------
-'git-verify-tag-script' [ --option ] <args>...
+'git-verify-tag-script' <tag>
 
 DESCRIPTION
 -----------
-Does something not yet documented.
-
+Validates the gpg signature created by git-tag-script.
 
 OPTIONS
 -------
---option::
-       Some option not yet documented.
-
-<args>...::
-       Some argument not yet documented.
-
+<tag>::
+       SHA1 identifier of a git tag object.
 
 Author
 ------
index 55d63d9432673878268ae9be4ba973b12a384b70..f63cbdd3727237b02c5be5b6f164dcae1fefd2f6 100644 (file)
@@ -1,6 +1,6 @@
 git(7)
 ======
-v0.99.4, Aug 2005
+v0.99.5, Aug 2005
 
 NAME
 ----
@@ -16,11 +16,19 @@ DESCRIPTION
 
 This is reference information for the core git commands.
 
+Before reading this cover to cover, you may want to take a look
+at the link:tutorial.html[tutorial] document.
+
 The Discussion section below contains much useful definition and
 clarification info - read that first.  And of the commands, I suggest
 reading link:git-update-cache.html[git-update-cache] and
 link:git-read-tree.html[git-read-tree] first - I wish I had!
 
+After you get the general feel from the tutorial and this
+overview page, you may want to take a look at the
+link:howto-index.html[howto] documents.
+
+
 David Greaves <david@dgreaves.com>
 08/05/05
 
@@ -187,6 +195,18 @@ link:git-update-server-info.html[git-update-server-info]::
 
 Porcelain-ish Commands
 ----------------------
+link:git-revert-script.html[git-revert-script]::
+       Revert an existing commit.
+
+link:git-rebase-script.html[git-rebase-script]::
+       Rebase local commits to new upstream head.
+
+link:git-add-script.html[git-add-script]::
+       Add paths to the index file.
+
+link:git-branch-script.html[git-branch-script]::
+       Create and Show branches.
+
 link:git-whatchanged.html[git-whatchanged]::
        Shows commit logs and differences they introduce.
 
@@ -205,7 +225,16 @@ link:git-fetch-script.html[git-fetch-script]::
 link:git-pull-script.html[git-pull-script]::
        Fetch from and merge with a remote repository.
 
-ulink:git-commit-script.html[git-commit-script]::
+link:git-resolve-script.html[git-resolve-script]::
+       Merge two commits.
+
+link:git-octopus-script.html[git-octopus-script]::
+       Merge more than two commits.
+
+link:git-push-script.html[git-push-script]::
+       Update remote refs along with associated objects.
+
+link:git-commit-script.html[git-commit-script]::
        Record changes to the repository.
 
 link:git-show-branch.html[git-show-branch]::
@@ -220,11 +249,17 @@ link:git-rename-script.html[git-rename]::
 link:git-ls-remote-script.html[git-ls-remote-script]::
        Shows references in a remote or local repository.
 
+link:git-verify-tag-script.html[git-verify-tag-script]::
+       Check the GPG signature of tag.
+
 
 Ancillary Commands
 ------------------
 Manipulators:
 
+link:git-relink-script.html[git-relink-script]::
+       Hardlink common objects in local repositories.
+
 link:git-apply-patch-script.html[git-apply-patch-script]::
        Sample script to apply the diffs from git-diff-*
 
@@ -237,9 +272,6 @@ link:git-merge-one-file-script.html[git-merge-one-file-script]::
 link:git-prune-script.html[git-prune-script]::
        Prunes all unreachable objects from the object database
 
-link:git-resolve-script.html[git-resolve-script]::
-       Script used to merge two trees
-
 link:git-tag-script.html[git-tag-script]::
        An example script to create a tag object signed with GPG
 
@@ -249,6 +281,15 @@ link:git-cvsimport-script.html[git-cvsimport-script]::
 
 Interrogators:
 
+link:git-patch-id.html[git-patch-id]::
+       Compute unique ID for a patch.
+
+link:git-count-objects-script.html[git-count-objects-script]::
+       Count unpacked number of objects and their disk consumption.
+
+link:git-cherry.html[git-cherry]::
+       Find commits not merged upstream.
+
 link:git-diff-helper.html[git-diff-helper]::
        Generates patch format output for git-diff-*
 
@@ -258,6 +299,9 @@ link:git-ssh-push.html[git-ssh-push]::
 link:git-send-email-script.html[git-send-email]::
        Send patch e-mails out of "format-patch --mbox" output.
 
+link:git-sh-setup-script.html[git-sh-setup-script]::
+       Common git shell script setup code.
+
 
 Commands not yet documented
 ---------------------------
@@ -274,30 +318,18 @@ link:git-mailinfo.html[git-mailinfo]::
 link:git-mailsplit.html[git-mailsplit]::
        git-mailsplit.
 
-link:git-add-script.html[git-add-script]::
-       git-add-script.
-
 link:git-bisect-script.html[git-bisect-script]::
        git-bisect-script.
 
-link:git-branch-script.html[git-branch-script]::
-       git-branch-script.
-
 link:git-build-rev-cache.html[git-build-rev-cache]::
        git-build-rev-cache.
 
 link:git-checkout-script.html[git-checkout-script]::
        git-checkout-script.
 
-link:git-cherry.html[git-cherry]::
-       git-cherry.
-
 link:git-clone-dumb-http.html[git-clone-dumb-http]::
        git-clone-dumb-http.
 
-link:git-count-objects-script.html[git-count-objects-script]::
-       git-count-objects-script.
-
 link:git-daemon.html[git-daemon]::
        git-daemon.
 
@@ -310,18 +342,6 @@ link:git-format-patch-script.html[git-format-patch-script]::
 link:git-get-tar-commit-id.html[git-get-tar-commit-id]::
        git-get-tar-commit-id.
 
-link:git-patch-id.html[git-patch-id]::
-       git-patch-id.
-
-link:git-push-script.html[git-push-script]::
-       git-push-script.
-
-link:git-rebase-script.html[git-rebase-script]::
-       git-rebase-script.
-
-link:git-relink-script.html[git-relink-script]::
-       git-relink-script.
-
 link:git-request-pull-script.html[git-request-pull-script]::
        git-request-pull-script.
 
@@ -331,21 +351,12 @@ link:git-reset-script.html[git-reset-script]::
 link:git-rev-parse.html[git-rev-parse]::
        git-rev-parse.
 
-link:git-revert-script.html[git-revert-script]::
-       git-revert-script.
-
-link:git-sh-setup-script.html[git-sh-setup-script]::
-       git-sh-setup-script.
-
 link:git-show-rev-cache.html[git-show-rev-cache]::
        git-show-rev-cache.
 
 link:git-stripspace.html[git-stripspace]::
        git-stripspace.
 
-link:git-verify-tag-script.html[git-verify-tag-script]::
-       git-verify-tag-script.
-
 link:gitk.html[gitk]::
        gitk.
 
index 7456cffd3306f83ce466a5a4afbdadc4fe980fb1..a069b7bb0cfbdacfc0ac2dd2183981b806792805 100644 (file)
@@ -27,14 +27,20 @@ blob object::
 
 tree object::
        An object containing a list of file names and modes along with refs
-       to the associated blob and/or tree objects. A tree object is
-       equivalent to a directory.
+       to the associated blob and/or tree objects. A tree is equivalent
+       to a directory.
 
 tree::
        Either a working tree, or a tree object together with the
        dependent blob and tree objects (i.e. a stored representation
        of a working tree).
 
+DAG::
+       Directed acyclic graph. The commit objects form a directed acyclic
+       graph, because they have parents (directed), and the graph of commit
+       objects is acyclic (there is no chain which begins and ends with the
+       same object).
+
 index::
        A collection of files with stat information, whose contents are
        stored as objects. The cache is a stored version of your working
@@ -142,6 +148,10 @@ merge::
        merge uses heuristics to accomplish that. Evidently, an automatic
        merge can fail.
 
+octopus::
+       To merge more than two branches. Also denotes an intelligent
+       predator.
+
 resolve::
        The action of fixing up manually what a failed automatic merge
        left behind.
diff --git a/Documentation/howto-index.sh b/Documentation/howto-index.sh
new file mode 100755 (executable)
index 0000000..f9d3e57
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+cat <<\EOF
+GIT Howto Index
+===============
+
+Here is a collection of mailing list postings made by various
+people describing how they use git in their workflow.
+
+EOF
+
+for txt
+do
+       title=`expr "$txt" : '.*/\(.*\)\.txt$'`
+       from=`sed -ne '
+       /^$/q
+       /^From:[        ]/{
+               s///
+               s/^[    ]*//
+               s/[     ]*$//
+               s/^/by /
+               p
+       }
+       ' "$txt"`
+
+       abstract=`sed -ne '
+       /^Abstract:[    ]/{
+               s/^[^   ]*//
+               x
+               s/.*//
+               x
+               : again
+               /^[     ]/{
+                       s/^[    ]*//
+                       H
+                       n
+                       b again
+               }
+               x
+               p
+               q
+       }' "$txt"`
+
+       echo "* link:$txt[$title] $from
+$abstract
+
+"
+
+done
index ae9094157c884249c33cb6f6b72cdb7f13e1746c..132d5eca66ecd095c14b07a3c6a01fd9abc125bd 100644 (file)
@@ -3,6 +3,11 @@ From: Linus Torvalds <torvalds@osdl.org>
 To: Dave Jones <davej@redhat.com>
 cc: git@vger.kernel.org
 Subject: Re: Fwd: Re: git checkout -f branch doesn't remove extra files
+Abstract: In this article, Linus talks about building a tarball,
+ incremental patch, and ChangeLog, given a base release and two
+ rc releases, following the convention of giving the patch from
+ the base release and the latest rc, with ChangeLog between the
+ last rc and the latest rc.
 
 On Sat, 13 Aug 2005, Dave Jones wrote:
 >
index 8299ca5cdcc42fb3fc9a255c9fedd26de51a08db..6cc1c7921f0bab8ec2c2b02e47594f57246b141b 100644 (file)
@@ -3,6 +3,9 @@ From:   Linus Torvalds <torvalds@osdl.org>
 To:    Steve French <smfrench@austin.rr.com>
 cc:    git@vger.kernel.org
 Subject: Re: sending changesets from the middle of a git tree
+Abstract: In this article, Linus demonstrates how a broken commit
+ in a sequence of commits can be removed by rewinding the head and
+ reapplying selected changes.
 
 On Sat, 13 Aug 2005, Linus Torvalds wrote:
 
index 8109b7ff26dc2010539f756ea47fda11483289a9..f627e4271c40fc2c4b28f825828e205b2fc8cb88 100644 (file)
@@ -3,6 +3,11 @@ To:    git@vger.kernel.org
 Cc:    Petr Baudis <pasky@suse.cz>, Linus Torvalds <torvalds@osdl.org>
 Subject: Re: sending changesets from the middle of a git tree
 Date:  Sun, 14 Aug 2005 18:37:39 -0700
+Abstract: In this article, JC talks about how he rebases the
+ public "pu" branch using the core GIT tools when he updates
+ the "master" branch, and how "rebase" works.  Also discussed
+ is how this applies to individual developers who sends patches
+ upstream.
 
 Petr Baudis <pasky@suse.cz> writes:
 
diff --git a/Documentation/howto/rebuild-from-update-hook.txt b/Documentation/howto/rebuild-from-update-hook.txt
new file mode 100644 (file)
index 0000000..ebd025d
--- /dev/null
@@ -0,0 +1,83 @@
+Subject: [HOWTO] Using post-update hook
+Message-ID: <7vy86o6usx.fsf@assigned-by-dhcp.cox.net>
+From: Junio C Hamano <junkio@cox.net>
+Date: Fri, 26 Aug 2005 18:19:10 -0700
+Abstract: In this how-to article, JC talks about how he
+ uses the post-update hook to automate git documentation page
+ shown at http://www.kernel.org/pub/software/scm/git/docs/.
+
+The pages under http://www.kernel.org/pub/software/scm/git/docs/
+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
+when I took over git maintainership from Linus.
+
+The directories relevant to this how-to are these two:
+
+    /pub/scm/git/git.git/      The public git repository.
+    /pub/software/scm/git/docs/        The HTML documentation page.
+
+So I made a repository to generate the documentation under my
+home directory over there.
+
+    $ cd
+    $ mkdir doc-git && cd doc-git
+    $ git clone /pub/scm/git/git.git/ docgen
+
+What needs to happen is to update the $HOME/doc-git/docgen/
+working tree, build HTML docs there and install the result in
+/pub/software/scm/git/docs/ directory.  So I wrote a little
+script:
+
+    $ cat >dododoc.sh <<\EOF
+    #!/bin/sh
+    cd $HOME/doc-git/docgen || exit
+
+    unset GIT_DIR
+
+    git pull /pub/scm/git/git.git/ master &&
+    cd Documentation &&
+    make install-webdoc
+    EOF
+
+Initially I used to run this by hand whenever I push into the
+public git repository.  Then I did a cron job that ran twice a
+day.  The current round uses the post-update hook mechanism,
+like this:
+
+    $ cat >/pub/scm/git/git.git/hooks/post-update <<\EOF
+    #!/bin/sh
+    #
+    # An example hook script to prepare a packed repository for use over
+    # dumb transports.
+    #
+    # To enable this hook, make this file executable by "chmod +x post-update".
+
+    case " $* " in
+    *' refs/heads/master '*)
+            echo $HOME/doc-git/dododoc.sh | at now
+            ;;
+    esac
+    exec git-update-server-info
+    EOF
+    $ chmod +x /pub/scm/git/git.git/hooks/post-update
+
+There are three 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
+   of refs that have been updated as arguments.  My post-update
+   runs the dododoc.sh script only when the master head is
+   updated.
+
+ - When update-hook is run, GIT_DIR is set to '.' by the calling
+   receive-pack.  This is inherited by the dododoc.sh run via
+   the "at" command, and needs to be unset; otherwise, "git
+   pull" it does into $HOME/doc-git/docgen/ repository would not
+   work correctly.
+
+ - 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.
+
index 52fa4c012a8a6fbef9ac9beec738a3446f2392be..b3b4d2c97aa4ccdffc3772ef4e745e14d323a995 100644 (file)
@@ -1,16 +1,16 @@
 Date: Mon, 15 Aug 2005 12:17:41 -0700
 From: tony.luck@intel.com
 Subject: Some tutorial text (was git/cogito workshop/bof at linuxconf au?)
+Abstract: In this article, Tony Luck discusses how he uses GIT
+ as a Linux subsystem maintainer.
 
 Here's something that I've been putting together on how I'm using
 GIT as a Linux subsystem maintainer.
 
-I suspect that I'm a bit slap-happy with the "git checkout" commands in
-the examples below, and perhaps missing some of the _true-git_ ways of
-doing things.
-
 -Tony
 
+Last updated w.r.t. GIT 0.99.5
+
 Linux subsystem maintenance using GIT
 -------------------------------------
 
@@ -48,24 +48,38 @@ Change directory into the cloned tree you just created
 
  $ cd work
 
-Make a GIT branch named "linus", and rename the "origin" branch as linus too:
+Set up a remotes file so that you can fetch the latest from Linus' master
+branch into a local branch named "linus":
+
+ $ cat > .git/remotes/linus
+ URL: rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+ Pull: master:linus
+ ^D
 
- $ git checkout -b linus
- $ mv .git/branches/origin .git/branches/linus
+and create the linus branch:
+
+ $ git branch linus
 
 The "linus" branch will be used to track the upstream kernel.  To update it,
 you simply run:
 
- $ git checkout linus && git pull linus
+ $ git fetch linus
+
+you can do this frequently (and it should be safe to do so with pending
+work in your tree, but perhaps not if you are in mid-merge).
 
-you can do this frequently (as long as you don't have any uncommited work
-in your tree).
+If you need to keep track of other public trees, you can add remote branches
+for them too:
 
-If you need to keep track of other public trees, you can add branches for
-them too:
+ $ git branch another
+ $ cat > .git/remotes/another
+ URL: ... insert URL here ...
+ Pull: name-of-branch-in-this-remote-tree:another
+ ^D
 
- $ git checkout -b another linus
- $ echo URL-for-another-public-tree > .git/branches/another
+and run:
+
+ $ git fetch another
 
 Now create the branches in which you are going to work, these start
 out at the current tip of the linus branch.
@@ -78,15 +92,25 @@ These can be easily kept up to date by merging from the "linus" branch:
  $ git checkout test && git resolve test linus "Auto-update from upstream"
  $ git checkout release && git resolve release linus "Auto-update from upstream"
 
-Set up so that you can push upstream to your public tree:
+Set up so that you can push upstream to your public tree (you need to
+log-in to the remote system and create an empty tree there before the
+first push).
 
- $ echo master.kernel.org:/ftp/pub/scm/linux/kernel/git/aegl/linux-2.6.git > .git/branches/origin
+ $ cat > .git/remotes/mytree
+ URL: master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
+ Push: release
+ Push: test
+ ^D
 
-and then push each of the test and release branches using:
+and the push both the test and release trees using:
 
- $ git push origin test
-and
- $ git push origin release
+ $ git push mytree
+
+or push just one of the test and release branches using:
+
+ $ git push mytree test
+or
+ $ git push mytree release
 
 Now to apply some patches from the community.  Think of a short
 snappy name for a branch to hold this patch (or related group of
@@ -169,9 +193,9 @@ test|release)
        git checkout $1 && git resolve $1 linus "Auto-update from upstream"
        ;;
 linus)
-       before=$(cat .git/HEAD)
-       git checkout linus && git pull linus
-       after=$(cat .git/HEAD)
+       before=$(cat .git/refs/heads/linus)
+       git fetch linus
+       after=$(cat .git/refs/heads/linus)
        if [ $before != $after ]
        then
                git-whatchanged $after ^$before | git-shortlog
diff --git a/Documentation/install-webdoc.sh b/Documentation/install-webdoc.sh
new file mode 100755 (executable)
index 0000000..1f534f1
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+T="$1"
+
+for h in *.html howto/*.txt
+do
+       diff -u "$T/$h" "$h" || {
+               echo >&2 "# install $h $T/$h"
+               rm -f "$T/$h"
+               mkdir -p `dirname "$T/$h"`
+               cp "$h" "$T/$h"
+       }
+done
+strip_leading=`echo "$T/" | sed -e 's|.|.|g'`
+for th in "$T"/*.html "$T"/howto/*.txt
+do
+       h=`expr "$th" : "$strip_leading"'\(.*\)'`
+       case "$h" in
+       index.html) continue ;;
+       esac
+       test -f "$h" && continue
+       echo >&2 "# rm -f $th"
+       rm -f "$th"
+done
+ln -sf git.html "$T/index.html"
index 7ae4ba0bd895dbc1adc94d893cf8b5aa8d29a108..8f6b68cb5514958570196b4c3f725467c0279ed3 100644 (file)
                Local directory
                        /path/to/repo.git/
 
-       In addition to that, as a short-hand, the name of a file
-       in $GIT_DIR/branches directory can be specified; the
-       named file should contain a single line, a URL in one of
-       the above formats, optionally followed by a hash '#' and
-       the name of remote head.
-
-<head>::
-       The remote head name to fetch from.  That is, make the
-       objects reachable from the commit recorded in
-       $GIT_DIR/refs/heads/<head> in the remote repository
-       available locally.
-
-tag <tag>::
-       The remote head tag to fetch from.  That is, make the
-       objects reachable from the commit recorded in
-       $GIT_DIR/refs/tags/<tag> in the remote repository
-       available locally.
+       In addition to the above, as a short-hand, the name of a
+       file in $GIT_DIR/remotes directory can be given; the
+       named file should be in the following format:
 
+               URL: one of the above URL format
+               Push: <refspec>...
+               Pull: <refspec>...
+
+       When such a short-hand is specified in place of
+       <repository> without <refspec> parameters on the command
+       line, <refspec>... specified on Push lines or Pull lines
+       are used for "git push" and "git fetch/pull",
+       respectively.
+
+       The name of a file in $GIT_DIR/branches directory can be
+       specified as an older notation short-hand; the named
+       file should contain a single line, a URL in one of the
+       above formats, optionally followed by a hash '#' and the
+       name of remote head (URL fragment notation).
+       $GIT_DIR/branches/<remote> file that stores a <url>
+       without the fragment is equivalent to have this in the
+       corresponding file in the $GIT_DIR/remotes/ directory
+
+               URL: <url>
+               Pull: refs/heads/master:<remote>
+
+       while having <url>#<head> is equivalent to
+
+               URL: <url>
+               Pull: refs/heads/<head>:<remote>
+
+<refspec>::
+       The canonical format of a <refspec> parameter is
+       '+?<src>:<dst>'; that is, an optional plus '+', followed
+       by the source ref, followed by a colon ':', followed by
+       the destination ref.
+
+       When used in "git push", the <src> side can be an
+       arbitrary "SHA1 expression" that can be used as an
+       argument to "git-cat-file -t".  E.g. "master~4" (push
+       four parents before the current master head).
+
+        For "git push", the local ref that matches <src> is used
+        to fast forward the remote ref that matches <dst>.  If
+        the optional plus '+' is used, the remote ref is updated
+        even if it does not result in a fast forward update.
+
+       For "git fetch/pull", the remote ref that matches <src>
+       is fetched, and if <dst> is not empty string, the local
+       ref that matches it is fast forwarded using <src>.
+       Again, if the optional plus '+' is used, the local ref
+       is updated even if it does not result in a fast forward
+       update.
+
+       Some short-cut notations are also supported.
+
+       * For backward compatibility, "tag" is almost ignored;
+          it just makes the following parameter <tag> to mean a
+          refspec "refs/tags/<tag>:refs/tags/<tag>".
+
+        * A parameter <ref> without a colon is equivalent to
+          <ref>: when pulling/fetching, and <ref>:<ref> when
+          pushing.  That is, do not store it locally if
+          fetching, and update the same name if pushing.
index 876a4afd17f75540417ba95f83e14fa4fc69cac7..866dbbe9b88ca8a6c235a45c4f5694b0a8d20750 100644 (file)
@@ -671,6 +671,7 @@ you have, you can say
        git branch
 
 which is nothing more than a simple script around "ls .git/refs/heads".
+There will be asterisk in front of the branch you are currently on.
 
 Sometimes you may wish to create a new branch _without_ actually
 checking it out and switching to it. If so, just use the command
@@ -892,18 +893,26 @@ pull from:
 
 It is likely that you will be pulling from the same remote
 repository from time to time. As a short hand, you can store
-the remote repository URL in a file under .git/branches/
+the remote repository URL in a file under .git/remotes/
 directory, like this:
 
-       mkdir -p .git/branches
-       echo rsync://kernel.org/pub/scm/git/git.git/ \
-           >.git/branches/linus
+------------------------------------------------
+mkdir -p .git/remotes/
+cat >.git/remotes/linus <<\EOF
+URL: http://www.kernel.org/pub/scm/git/git.git/
+EOF
+------------------------------------------------
 
 and use the filename to "git pull" instead of the full URL.
-The contents of a file under .git/branches can even be a prefix
+The URL specified in such file can even be a prefix
 of a full URL, like this:
 
-       echo rsync://kernel.org/pub/.../jgarzik/ >.git/branches/jgarzik
+------------------------------------------------
+cat >.git/remotes/jgarzik <<\EOF
+URL: http://www.kernel.org/pub/scm/linux/git/jgarzik/
+EOF
+------------------------------------------------
+
 
 Examples.
 
@@ -913,9 +922,9 @@ Examples.
 
 the above are equivalent to:
 
-       (1) git pull rsync://kernel.org/pub/scm/git/git.git/ HEAD
-       (2) git pull rsync://kernel.org/pub/scm/git/git.git/ tag v0.99.1
-       (3) git pull rsync://kernel.org/pub/.../jgarzik/netdev-2.6.git e100
+       (1) git pull http://www.kernel.org/pub/scm/git/git.git/ HEAD
+       (2) git pull http://www.kernel.org/pub/scm/git/git.git/ tag v0.99.1
+       (3) git pull http://www.kernel.org/pub/.../jgarzik/netdev-2.6.git e100
 
 
 Publishing your work
@@ -1169,18 +1178,43 @@ Working with Others, Shared Repository Style
 If you are coming from CVS background, the style of cooperation
 suggested in the previous section may be new to you. You do not
 have to worry. git supports "shared public repository" style of
-cooperation you are more familiar with as well.
-
-For this, you should set up a public repository on a machine
-that are reachable via SSH by people with "commit privileges".
-Put them in the same user group and make the repository writable
-by that group. Then, each committer would first merge with the
-head of the branch of choice, and run "git push" to update the
-branch at the public repository. "git push" refuses to update
-if the reference on the remote side is not an ancestor of the
-commit you are pushing, to prevent you from overwriting changes
-made by somebody else.
+cooperation you are probably more familiar with as well.
+
+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.
+
+Each committer would then:
+
+       - clone the shared repository to a local repository,
+
+------------------------------------------------
+$ git clone repo.shared.xz:/pub/scm/project.git/ my-project
+$ cd my-project
+$ hack away
+------------------------------------------------
+
+       - merge the work others might have done while you were
+          hacking away.
+
+------------------------------------------------
+$ git pull origin
+$ test the merge result
+------------------------------------------------
+
+       - push your work as the new head of the shared
+          repository.
+
+------------------------------------------------
+$ git push origin master
+------------------------------------------------
 
+If somebody else pushed into the same shared repository while
+you were working locally, the last step "git push" would
+complain, telling you that the remote "master" head does not
+fast forward.  You need to pull and merge those other changes
+back before you push your work when it happens.
 
 
 [ to be continued.. cvsimports ]
index ac4f2110dcab8a66a4808a92f569b1eaaa10b699..c0fdaa701f973ec84a9c4524af451432ee2adcf0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -32,7 +32,7 @@
 
 # DEFINES += -DUSE_STDEV
 
-GIT_VERSION = 0.99.4
+GIT_VERSION = 0.99.5
 
 CFLAGS = -g -O2 -Wall
 ALL_CFLAGS = $(CFLAGS) $(DEFINES)
@@ -64,13 +64,13 @@ SCRIPTS=git git-apply-patch-script git-merge-one-file-script git-prune-script \
        git-reset-script git-add-script git-checkout-script git-clone-script \
        gitk git-cherry git-rebase-script git-relink-script git-repack-script \
        git-format-patch-script git-sh-setup-script git-push-script \
-       git-branch-script git-parse-remote git-verify-tag-script \
+       git-branch-script git-parse-remote-script git-verify-tag-script \
        git-ls-remote-script git-clone-dumb-http git-rename-script \
        git-request-pull-script git-bisect-script
 
 SCRIPTS += git-count-objects-script
-# SCRIPTS += git-send-email-script
 SCRIPTS += git-revert-script
+SCRIPTS += git-octopus-script
 
 PROG=   git-update-cache git-diff-files git-init-db git-write-tree \
        git-read-tree git-commit-tree git-cat-file git-fsck-cache \
@@ -86,6 +86,10 @@ PROG=   git-update-cache git-diff-files git-init-db git-write-tree \
        git-show-index git-daemon git-var git-peek-remote git-show-branch \
        git-update-server-info git-show-rev-cache git-build-rev-cache
 
+ifdef WITH_SEND_EMAIL
+SCRIPTS += git-send-email-script
+endif
+
 ifndef NO_CURL
        PROG+= git-http-pull
 endif
diff --git a/apply.c b/apply.c
index ee59be643eb5f95ed021921b1b76d37135cab5ac..e87190ea3868f1379d557226e4779c36546ffe3e 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -387,7 +387,7 @@ static char *git_header_name(char *line)
                default:
                        continue;
                case '\n':
-                       break;
+                       return NULL;
                case '\t': case ' ':
                        second = name+len;
                        for (;;) {
diff --git a/cache.h b/cache.h
index e4f4664572ae3b6d58f04a87fe57ab8b460dd48f..d407f390010c8db7c9e469675bbd7f5a8ece1fa2 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -313,6 +313,7 @@ struct ref {
        struct ref *next;
        unsigned char old_sha1[20];
        unsigned char new_sha1[20];
+       unsigned char force;
        struct ref *peer_ref; /* when renaming */
        char name[];
 };
index c0bf869e96ea1189209c3d0bbef6fc27b2499581..825c439accfbb4be4daa21a4d8b33addca0cd8b2 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -82,15 +82,26 @@ int path_match(const char *path, int nr, char **match)
 struct refspec {
        char *src;
        char *dst;
+       char force;
 };
 
+/*
+ * A:B means fast forward remote B with local A.
+ * +A:B means overwrite remote B with local A.
+ * +A is a shorthand for +A:A.
+ * A is a shorthand for A:A.
+ */
 static struct refspec *parse_ref_spec(int nr_refspec, char **refspec)
 {
        int i;
-       struct refspec *rs = xmalloc(sizeof(*rs) * (nr_refspec + 1));
+       struct refspec *rs = xcalloc(sizeof(*rs), (nr_refspec + 1));
        for (i = 0; i < nr_refspec; i++) {
                char *sp, *dp, *ep;
                sp = refspec[i];
+               if (*sp == '+') {
+                       rs[i].force = 1;
+                       sp++;
+               }
                ep = strchr(sp, ':');
                if (ep) {
                        dp = ep + 1;
@@ -216,8 +227,10 @@ static int match_explicit_refs(struct ref *src, struct ref *dst,
                        error("dst ref %s receives from more than one src.",
                              matched_dst->name);
                }
-               else
+               else {
                        matched_dst->peer_ref = matched_src;
+                       matched_dst->force = rs[i].force;
+               }
        }
        return -errs;
 }
diff --git a/debian/.gitignore b/debian/.gitignore
new file mode 100644 (file)
index 0000000..335ce9c
--- /dev/null
@@ -0,0 +1,6 @@
+git-core
+git-tk
+*.debhelper
+*.substvars
+build-stamp
+files
index 2788cdd9095fee149ed7c11f4bf1d350462cd46e..5b7b4d3ff3e3fb228588c320c52f07a8e0a0cd91 100644 (file)
@@ -1,3 +1,16 @@
+git-core (0.99.5-1) unstable; urgency=low
+
+  * Enable git-send-email-script on Debian.  There is no reason to shy
+    away from it, since we have the necessary Perl modules available.
+
+ -- Junio C Hamano <junkio@cox.net>  Thu, 25 Aug 2005 14:16:59 -0700
+
+git-core (0.99.5-0) unstable; urgency=low
+
+  * GIT 0.99.5
+
+ -- Junio C Hamano <junkio@cox.net>  Wed, 10 Aug 2005 22:05:00 -0700
+
 git-core (0.99.4-4) unstable; urgency=low
 
   * Mark git-tk as architecture neutral.
index 5df89dde323b1d5e580ad04ff83a488e236fbfe2..6735a0da031d1ed0a73e8868bb146c0cfbfa0db5 100644 (file)
@@ -2,14 +2,15 @@ Source: git-core
 Section: devel
 Priority: optional
 Maintainer: Junio C Hamano <junkio@cox.net>
-Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev, asciidoc > 6.0.3, xmlto, debhelper (>= 4.0.0)
+Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev, asciidoc (>= 6.0.3), xmlto, debhelper (>= 4.0.0)
 Standards-Version: 3.6.1
 
 Package: git-core
 Architecture: any
 Depends: ${shlibs:Depends}, ${perl:Depends}, ${misc:Depends}, patch, rcs
 Recommends: rsync, curl, ssh, libmail-sendmail-perl, libemail-valid-perl
-Conflicts: git
+Suggests: cogito
+Conflicts: git, cogito (<< 0.13)
 Description: The git content addressable filesystem
  GIT comes in two layers. The bottom layer is merely an extremely fast
  and flexible filesystem-based database designed to store directory trees
index f1bbea81197f454818c65ff1d5d7e448886faef2..1ed46333d186aac0ec12ea3aeb7684d843014b3e 100644 (file)
@@ -1,6 +1,5 @@
 Document: git-core
-Title: git-core
-Author: 
+Title: git reference
 Abstract: This manual describes git
 Section: Devel
 
@@ -9,4 +8,4 @@ Index: /usr/share/doc/git-core/git.html
 Files: /usr/share/doc/git-core/*.html
 
 Format: text
-Files: /usr/share/doc/git-core/git-core.txt
+Files: /usr/share/doc/git-core/git.txt*
index 3801e7564b41e4f917d8eb27ad174c1f822c5b2f..e54f897ce3fb68416bc86e844c9702eb8ca8e005 100644 (file)
@@ -1 +1,3 @@
 /usr/bin/gitk
+/usr/share/man/man1/gitk.*
+/usr/share/doc/git-core/gitk.*
index c46b4d9466afc9e40522e1f0e842add623dd4d21..86464bf30b7fb578f415cc2ac9950a68d3a1917f 100755 (executable)
@@ -25,6 +25,9 @@ else
        export MOZILLA_SHA1=YesPlease
 endif
 
+# We do have the requisite perl modules in the mainline, and
+# have no reason to shy away from this script.
+export WITH_SEND_EMAIL=YesPlease
 
 PREFIX := /usr
 MANDIR := /usr/share/man/
index 29b25f4a4ce67a9d2532c617b93a9e5297cc4249..0c5c10750e34f76327df0f57ce26417b18dd8963 100755 (executable)
@@ -58,7 +58,7 @@ bisect_start() {
 bisect_bad() {
        bisect_autostart
         case "$#" in 0 | 1) ;; *) usage ;; esac
-       rev=$(git-rev-parse --revs-only --verify --default HEAD "$@") || exit
+       rev=$(git-rev-parse --verify --default HEAD "$@") || exit
        echo "$rev" > "$GIT_DIR/refs/bisect/bad"
        bisect_auto_next
 }
@@ -67,7 +67,7 @@ bisect_good() {
        bisect_autostart
         case "$#" in
        0)    revs=$(git-rev-parse --verify HEAD) || exit ;;
-       *)    revs=$(git-rev-parse --revs-only "$@") || exit ;;
+       *)    revs=$(git-rev-parse --revs-only --no-flags "$@") || exit ;;
        esac
        for rev in $revs
        do
index a6dfeaf55fb917de346132a94e9d3d123223eecd..0ecbd239acf0d035ba1a7c9471c2b29b3bb4b884 100755 (executable)
@@ -25,7 +25,7 @@ case "$#" in
        head="$2^0" ;;
 esac
 branchname="$1"
-rev=$(git-rev-parse --revs-only --verify "$head") || exit
+rev=$(git-rev-parse --verify "$head") || exit
 
 [ -e "$GIT_DIR/refs/heads/$branchname" ] && die "$branchname already exists"
 
index a37740713ed747a18b7ee5415e41e5bd57834c48..9feff149acc87326e13f96db17257235e78c42db 100755 (executable)
@@ -72,4 +72,6 @@ if [ "$?" -eq 0 ]; then
        fi
        [ "$branch" ] && ln -sf "refs/heads/$branch" "$GIT_DIR/HEAD"
        rm -f "$GIT_DIR/MERGE_HEAD"
+else
+       exit 1
 fi
index 99c2459631f2bdcc6382bd2b5fc03090e1888ee3..f988b8c9c79fbb9ec9c3cad556cb4c9d51984475 100755 (executable)
@@ -127,6 +127,8 @@ yes,yes)
 esac
 
 # Update origin.
-mkdir -p "$D/.git/branches/" &&
-rm -f "$D/.git/branches/origin" &&
-echo "$repo" >"$D/.git/branches/origin"
+mkdir -p "$D/.git/remotes/" &&
+rm -f "$D/.git/remotes/origin" &&
+echo >"$D/.git/remotes/origin" \
+"URL: $repo
+Pull: master:origin"
index 5c5f564a28e779de333ea96c35c95993f7535869..4987e37861adac29af5bfd03a8d8e1e6932338e0 100755 (executable)
@@ -110,57 +110,51 @@ t)
        fi
 esac
 
+if [ ! -r "$GIT_DIR/HEAD" ]
+then
+       echo "#"
+       echo "# Initial commit"
+       echo "#"
+       git-ls-files | sed 's/^/# New file: /'
+       echo "#"
+elif [ -f "$GIT_DIR/MERGE_HEAD" ]; then
+       echo "#"
+       echo "# It looks like your may be committing a MERGE."
+       echo "# If this is not correct, please remove the file"
+       echo "# $GIT_DIR/MERGE_HEAD"
+       echo "# and try again"
+       echo "#"
+fi >.editmsg
+if test "$log_message" != ''
+then
+       echo "$log_message"
+elif test "$logfile" != ""
+then
+       if test "$logfile" = -
+       then
+               test -t 0 &&
+               echo >&2 "(reading log message from standard input)"
+               cat
+       else
+               cat <"$logfile"
+       fi
+elif test "$use_commit" != ""
+then
+       git-cat-file commit "$use_commit" | sed -e '1,/^$/d'
+fi | git-stripspace >>.editmsg
+
 PARENTS="-p HEAD"
 if [ ! -r "$GIT_DIR/HEAD" ]; then
        if [ -z "$(git-ls-files)" ]; then
                echo Nothing to commit 1>&2
                exit 1
        fi
-       {
-               echo "#"
-               echo "# Initial commit"
-               case "$no_edit" in
-               t) echo "# (ignoring your commit message for initial commit)"
-                  no_edit= 
-               esac
-               echo "#"
-               git-ls-files | sed 's/^/# New file: /'
-               echo "#"
-       } >.editmsg
        PARENTS=""
-       no_edit=
 else
        if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
-               {
-               echo "#"
-               echo "# It looks like your may be committing a MERGE."
-               echo "# If this is not correct, please remove the file"
-               echo "# $GIT_DIR/MERGE_HEAD"
-               echo "# and try again"
-               case "$no_edit" in
-               t) echo "# (ignoring your commit message for merge commit)"
-                  no_edit= 
-               esac
-               echo "#"
-               } |
-               git-stripspace >.editmsg
                PARENTS="-p HEAD -p MERGE_HEAD"
-       elif test "$log_message" != ''
-       then
-               echo "$log_message" |
-               git-stripspace >.editmsg
-       elif test "$logfile" != ""
-       then
-               if test "$logfile" = -
-               then
-                       test -t 0 &&
-                       echo >&2 "(reading log message from standard input)"
-                       cat
-               else
-                       cat <"$logfile"
-               fi |
-               git-stripspace >.editmsg
-       elif test "$use_commit" != ""
+       fi
+       if test "$use_commit" != ""
        then
                pick_author_script='
                /^author /{
@@ -188,23 +182,21 @@ else
                export GIT_AUTHOR_NAME
                export GIT_AUTHOR_EMAIL
                export GIT_AUTHOR_DATE
-               git-cat-file commit "$use_commit" |
-               sed -e '1,/^$/d' |
-               git-stripspace >.editmsg
        fi
-
        case "$signoff" in
        t)
                git-var GIT_COMMITTER_IDENT | sed -e '
                        s/>.*/>/
-                       s/^/Signed-off-by: /' >>.editmsg ;;
+                       s/^/Signed-off-by: /
+               ' >>.editmsg
+               ;;
        esac
        git-status-script >>.editmsg
 fi
 if [ "$?" != "0" -a ! -f $GIT_DIR/MERGE_HEAD ]
 then
-       cat .editmsg
-       rm .editmsg
+       rm -f .editmsg
+       git-status-script
        exit 1
 fi
 case "$no_edit" in
index ea097144f712f9ef1beb0531f1bf945db9485c3f..dd94edeb38eb47dc6abf5e00c1a5d8c067a76f74 100755 (executable)
 #!/bin/sh
 #
 . git-sh-setup-script || die "Not a git archive"
-. git-parse-remote "$@"
-merge_repo="$_remote_repo"
-merge_head="$_remote_head"
-merge_store="$_remote_store"
-
-TMP_HEAD="$GIT_DIR/TMP_HEAD"
-
-case "$merge_repo" in
-http://* | https://*)
-        if [ -n "$GIT_SSL_NO_VERIFY" ]; then
-            curl_extra_args="-k"
-        fi
-       _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' &&
-       _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" &&
-       head=$(curl -nsf $curl_extra_args "$merge_repo/$merge_head") &&
-       expr "$head" : "$_x40\$" >/dev/null || {
-               echo >&2 "Failed to fetch $merge_head from $merge_repo"
-               exit 1
-       }
-       echo Fetching "$merge_head" using http
-       git-http-pull -v -a "$head" "$merge_repo/" || exit
-       ;;
-rsync://*)
-       rsync -L "$merge_repo/$merge_head" "$TMP_HEAD" || exit 1
-       head=$(git-rev-parse TMP_HEAD)
-       rm -f "$TMP_HEAD"
-       rsync -avz --ignore-existing "$merge_repo/objects/" "$GIT_OBJECT_DIRECTORY/"
-       ;;
-*)
-       head=$(git-fetch-pack "$merge_repo" "$merge_head")
-       if h=`expr "$head" : '\([^ ][^ ]*\) '`
+. git-parse-remote-script
+_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
+_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+
+append=
+force=
+update_head_ok=
+while case "$#" in 0) break ;; esac
+do
+       case "$1" in
+       -a|--a|--ap|--app|--appe|--appen|--append)
+               append=t
+               ;;
+       -f|--f|--fo|--for|--forc|--force)
+               force=t
+               ;;
+       -u|--u|--up|--upd|--upda|--updat|--update|--update-|--update-h|\
+       --update-he|--update-hea|--update-head|--update-head-|\
+       --update-head-o|--update-head-ok)
+               update_head_ok=t
+               ;;
+       *)
+               break
+               ;;
+       esac
+       shift
+done
+
+case "$#" in
+0)
+       test -f "$GIT_DIR/branches/origin" ||
+               test -f "$GIT_DIR/remotes/origin" ||
+                       die "Where do you want to fetch from today?"
+       set origin ;;
+esac
+
+remote_nick="$1"
+remote=$(get_remote_url "$@")
+refs=
+rref=
+rsync_slurped_objects=
+
+if test "" = "$append"
+then
+       : >$GIT_DIR/FETCH_HEAD
+fi
+
+append_fetch_head () {
+    head_="$1"
+    remote_="$2"
+    remote_name_="$3"
+    remote_nick_="$4"
+    local_name_="$5"
+
+    # 2.6.11-tree tag would not be happy to be fed to resolve.
+    if git-cat-file commit "$head_" >/dev/null 2>&1
+    then
+       headc_=$(git-rev-parse --verify "$head_^0") || exit
+       note_="$headc_  $remote_name_ from $remote_nick_"
+       echo "$note_" >>$GIT_DIR/FETCH_HEAD
+       echo >&2 "* committish: $note_"
+    else
+       echo >&2 "* non-commit: $note_"
+    fi
+    if test "$local_name_" != ""
+    then
+       # We are storing the head locally.  Make sure that it is
+       # a fast forward (aka "reverse push").
+       fast_forward_local "$local_name_" "$head_" "$remote_" "$remote_name_"
+    fi
+}
+
+fast_forward_local () {
+    case "$1" in
+    refs/tags/*)
+       # Tags need not be pointing at commits so there
+       # is no way to guarantee "fast-forward" anyway.
+       if test -f "$GIT_DIR/$1"
        then
-           head=$h
+               echo >&2 "* $1: updating with $4"
+               echo >&2 "  from $3."
+       else
+               echo >&2 "* $1: storing $4"
+               echo >&2 "  from $3."
        fi
-       ;;
-esac || exit 1
+       echo "$2" >"$GIT_DIR/$1" ;;
 
-git-rev-parse --verify "$head" > /dev/null || exit 1
+    refs/heads/*)
+       # NEEDSWORK: use the same cmpxchg protocol here.
+       echo "$2" >"$GIT_DIR/$1.lock"
+       if test -f "$GIT_DIR/$1"
+       then
+           local=$(git-rev-parse --verify "$1^0") &&
+           mb=$(git-merge-base "$local" "$2") &&
+           case "$2,$mb" in
+           $local,*)
+               echo >&2 "* $1: same as $4"
+               echo >&2 "  from $3"
+               ;;
+           *,$local)
+               echo >&2 "* $1: fast forward to $4"
+               echo >&2 "  from $3"
+               ;;
+           *)
+               false
+               ;;
+           esac || {
+               echo >&2 "* $1: does not fast forward to $4"
+               case "$force,$single_force" in
+               t,* | *,t)
+                       echo >&2 "  from $3; forcing update."
+                       ;;
+               *)
+                       mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1.remote"
+                       echo >&2 "  from $3; leaving it in '$1.remote'"
+                       ;;
+               esac
+           }
+       else
+               echo >&2 "* $1: storing $4"
+               echo >&2 "  from $3."
+       fi
+       test -f "$GIT_DIR/$1.lock" &&
+           mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1"
+       ;;
+    esac
+}
 
-case "$merge_store" in
+case "$update_head_ok" in
 '')
+       orig_head=$(cat "$GIT_DIR/HEAD" 2>/dev/null)
        ;;
+esac
+
+for ref in $(get_remote_refs_for_fetch "$@")
+do
+    refs="$refs $ref"
+
+    # These are relative path from $GIT_DIR, typically starting at refs/
+    # but may be HEAD
+    if expr "$ref" : '\+' >/dev/null
+    then
+       single_force=t
+       ref=$(expr "$ref" : '\+\(.*\)')
+    else
+       single_force=
+    fi
+    remote_name=$(expr "$ref" : '\([^:]*\):')
+    local_name=$(expr "$ref" : '[^:]*:\(.*\)')
+
+    rref="$rref $remote_name"
+
+    # There are transports that can fetch only one head at a time...
+    case "$remote" in
+    http://* | https://*)
+       if [ -n "$GIT_SSL_NO_VERIFY" ]; then
+           curl_extra_args="-k"
+       fi
+       head=$(curl -nsf $curl_extra_args "$remote/$remote_name") &&
+       expr "$head" : "$_x40\$" >/dev/null ||
+               die "Failed to fetch $remote_name from $remote"
+       echo Fetching "$remote_name from $remote" using http
+       git-http-pull -v -a "$head" "$remote/" || exit
+       ;;
+    rsync://*)
+       TMP_HEAD="$GIT_DIR/TMP_HEAD"
+       rsync -L "$remote/$remote_name" "$TMP_HEAD" || exit 1
+       head=$(git-rev-parse TMP_HEAD)
+       rm -f "$TMP_HEAD"
+       test "$rsync_slurped_objects" || {
+           rsync -avz --ignore-existing "$remote/objects/" \
+               "$GIT_OBJECT_DIRECTORY/" || exit
+           rsync_slurped_objects=t
+       }
+       ;;
+    *)
+       # We will do git native transport with just one call later.
+       continue ;;
+    esac
+
+    append_fetch_head "$head" "$remote" "$remote_name" "$remote_nick" "$local_name"
+
+done
+
+case "$remote" in
+http://* | https://* | rsync://* )
+    ;; # we are already done.
 *)
-       echo "$head" > "$GIT_DIR/$merge_store"
-esac &&
+    git-fetch-pack "$remote" $rref |
+    while read sha1 remote_name
+    do
+       found=
+       single_force=
+       for ref in $refs
+       do
+           case "$ref" in
+           +$remote_name:*)
+               single_force=t
+               found="$ref"
+               break ;;
+           $remote_name:*)
+               found="$ref"
+               break ;;
+           esac
+       done
 
-# FETCH_HEAD is fed to git-resolve-script which will eventually be
-# passed to git-commit-tree as one of the parents.  Make sure we do
-# not give a tag object ID.
+       local_name=$(expr "$found" : '[^:]*:\(.*\)')
+       append_fetch_head "$sha1" "$remote" "$remote_name" "$remote_nick" "$local_name"
+    done
+    ;;
+esac
 
-git-rev-parse "$head^0" >"$GIT_DIR/FETCH_HEAD"
+# If the original head was empty (i.e. no "master" yet), or
+# if we were told not to worry, we do not have to check.
+case ",$update_head_ok,$orig_head," in
+*,, | t,* )
+       ;;
+*)
+       curr_head=$(cat "$GIT_DIR/HEAD" 2>/dev/null)
+       if test "$curr_head" != "$orig_head"
+       then
+               echo "$orig_head" >$GIT_DIR/HEAD
+               die "Cannot fetch into the current branch."
+       fi
+       ;;
+esac
index 9260f920559578feac9922a7c2ef781252567952..5716b29941bb5c005d0de63f916708a3fc774e01 100755 (executable)
@@ -1,4 +1,4 @@
 #!/bin/sh
-revs=$(git-rev-parse --revs-only --default HEAD "$@") || exit
+revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
 [ "$revs" ] || die "No HEAD ref"
 git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | LESS=-S ${PAGER:-less}
index 75f60278669851d627a9ff2f8e87c9382af72c6a..061a23135cee6a41ff23022672841d6061d52fd8 100755 (executable)
@@ -29,8 +29,8 @@ case ",$heads,$tags," in
 ,,,) heads=heads tags=tags other=other ;;
 esac
 
-. git-parse-remote "$1"
-peek_repo="$_remote_repo"
+. git-parse-remote-script
+peek_repo="$(get_remote_url "$@")"
 shift
 
 tmp=.ls-remote-$$
diff --git a/git-octopus-script b/git-octopus-script
new file mode 100755 (executable)
index 0000000..80edfd4
--- /dev/null
@@ -0,0 +1,103 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+# Resolve two or more trees recorded in $GIT_DIR/FETCH_HEAD.
+#
+. git-sh-setup-script || die "Not a git archive"
+
+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-cache --refresh ||
+       die "Your working tree is dirty."
+test "$(git-diff-cache --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 MSG= 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"
+       MSG="$MSG
+       $REPO"
+
+       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-cache -o git-merge-one-file-script -a || {
+               git-read-tree --reset "$head"
+               git-checkout-cache -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 ;;
+2)
+       echo "Not an Octopus; making an ordinary commit."
+       MSG="Merge "`expr "$MSG" : '.   \(.*\)'` ; # remove LF and TAB
+       ;;
+*)
+       # In an octopus, the original head is just one of the equals,
+       # so we should list it as such.
+       HEAD_LINK=`readlink "$GIT_DIR/HEAD"`
+       MSG="Octopus merge of the following:
+
+       $HEAD_LINK from .$MSG"
+       ;;
+esac
+result_commit=$(echo "$MSG" | git-commit-tree $MRT $PARENT)
+echo "Committed merge $result_commit"
+echo $result_commit >"$GIT_DIR"/HEAD
+git-diff-tree -p $head $result_commit | git-apply --stat
diff --git a/git-parse-remote b/git-parse-remote
deleted file mode 100755 (executable)
index 53c5842..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-: To be included in git-pull and git-fetch scripts.
-
-# A remote repository can be specified on the command line
-# in one of the following formats:
-#
-#      <repo>
-#      <repo> <head>
-#      <repo> tag <tag>
-#
-# where <repo> could be one of:
-#
-#      a URL (including absolute or local pathname)
-#      a short-hand
-#      a short-hand followed by a trailing path
-#
-# A short-hand <name> has a corresponding file $GIT_DIR/branches/<name>,
-# whose contents is a URL, possibly followed by a URL fragment #<head>
-# to name the default branch on the remote side to fetch from.
-
-_remote_repo= _remote_store= _remote_head= _remote_name=
-
-case "$1" in
-*:* | /* | ../* | ./* )
-       _remote_repo="$1"
-       ;;
-* )
-       # otherwise, it is a short hand.
-       case "$1" in
-       */*)
-               # a short-hand followed by a trailing path
-               _token=$(expr "$1" : '\([^/]*\)/')
-               _rest=$(expr "$1" : '[^/]*\(/.*\)$')
-               ;;
-       *)
-               _token="$1"
-               _rest=
-               _remote_store="refs/heads/$_token"
-               ;;
-       esac
-       test -f "$GIT_DIR/branches/$_token" ||
-       die "No such remote branch: $_token"
-
-       _remote_repo=$(cat "$GIT_DIR/branches/$_token")"$_rest"
-       ;;
-esac
-
-case "$_remote_repo" in
-*"#"*)
-       _remote_head=`expr "$_remote_repo" : '.*#\(.*\)$'`
-       _remote_repo=`expr "$_remote_repo" : '\(.*\)#'`
-       ;;
-esac
-
-_remote_name=$(echo "$_remote_repo" | sed 's|\.git/*$||')
-
-case "$2" in
-tag)
-       _remote_name="tag '$3' of $_remote_name"
-       _remote_head="refs/tags/$3"
-       _remote_store="$_remote_head"
-       ;;
-?*)
-       # command line specified a head explicitly; do not
-       # store the fetched head as a branch head.
-       _remote_name="head '$2' of $_remote_name"
-       _remote_head="refs/heads/$2"
-       _remote_store=''
-       ;;
-'')
-       case "$_remote_head" in
-       '')
-               _remote_head=HEAD ;;
-       *)
-               _remote_name="head '$_remote_head' of $_remote_name"
-               _remote_head="refs/heads/$_remote_head"
-               ;;
-       esac
-       ;;
-esac
diff --git a/git-parse-remote-script b/git-parse-remote-script
new file mode 100755 (executable)
index 0000000..cf37884
--- /dev/null
@@ -0,0 +1,151 @@
+#!/bin/sh
+
+. git-sh-setup-script || die "Not a git archive"
+
+get_data_source () {
+       case "$1" in
+       */*)
+               # Not so fast.  This could be the partial URL shorthand...
+               token=$(expr "$1" : '\([^/]*\)/')
+               remainder=$(expr "$1" : '[^/]*/\(.*\)')
+               if test -f "$GIT_DIR/branches/$token"
+               then
+                       echo branches-partial
+               else
+                       echo ''
+               fi
+               ;;
+       *)
+               if test -f "$GIT_DIR/remotes/$1"
+               then
+                       echo remotes
+               elif test -f "$GIT_DIR/branches/$1"
+               then
+                       echo branches
+               else
+                       echo ''
+               fi ;;
+       esac
+}
+
+get_remote_url () {
+       data_source=$(get_data_source "$1")
+       case "$data_source" in
+       '')
+               echo "$1" ;;
+       remotes)
+               sed -ne '/^URL: */{
+                       s///p
+                       q
+               }' "$GIT_DIR/remotes/$1" ;;
+       branches)
+               sed -e 's/#.*//' "$GIT_DIR/branches/$1" ;;
+       branches-partial)
+               token=$(expr "$1" : '\([^/]*\)/')
+               remainder=$(expr "$1" : '[^/]*/\(.*\)')
+               url=$(sed -e 's/#.*//' "$GIT_DIR/branches/$token")
+               echo "$url/$remainder"
+               ;;
+       *)
+               die "internal error: get-remote-url $1" ;;
+       esac
+}
+
+get_remote_default_refs_for_push () {
+       data_source=$(get_data_source "$1")
+       case "$data_source" in
+       '' | branches | branches-partial)
+               ;; # no default push mapping, just send matching refs.
+       remotes)
+               sed -ne '/^Push: */{
+                       s///p
+               }' "$GIT_DIR/remotes/$1" ;;
+       *)
+               die "internal error: get-remote-default-ref-for-push $1" ;;
+       esac
+}
+
+# Subroutine to canonicalize remote:local notation
+canon_refs_list_for_fetch () {
+       for ref
+       do
+               force=
+               case "$ref" in
+               +*)
+                       ref=$(expr "$ref" : '\+\(.*\)')
+                       force=+
+                       ;;
+               esac
+               expr "$ref" : '.*:' >/dev/null || ref="${ref}:"
+               remote=$(expr "$ref" : '\([^:]*\):')
+               local=$(expr "$ref" : '[^:]*:\(.*\)')
+               case "$remote" in
+               '') remote=HEAD ;;
+               *) remote="refs/heads/$remote" ;;
+               esac
+               case "$local" in
+               '') local= ;;
+               *) local="refs/heads/$local" ;;
+               esac
+               echo "${force}${remote}:${local}"
+       done
+}
+
+# Returns list of src: (no store), or src:dst (store)
+get_remote_default_refs_for_fetch () {
+       data_source=$(get_data_source "$1")
+       case "$data_source" in
+       '' | branches-partial)
+               echo "HEAD:" ;;
+       branches)
+               remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1")
+               case "$remote_branch" in '') remote_branch=master ;; esac
+               echo "refs/heads/${remote_branch}:refs/heads/$1"
+               ;;
+       remotes)
+               canon_refs_list_for_fetch $(sed -ne '/^Pull: */{
+                                               s///p
+                                       }' "$GIT_DIR/remotes/$1")
+               ;;
+       *)
+               die "internal error: get-remote-default-ref-for-push $1" ;;
+       esac
+}
+
+get_remote_refs_for_push () {
+       case "$#" in
+       0) die "internal error: get-remote-refs-for-push." ;;
+       1) get_remote_default_refs_for_push "$@" ;;
+       *) shift; echo "$@" ;;
+       esac
+}
+
+get_remote_refs_for_fetch () {
+       case "$#" in
+       0)
+           die "internal error: get-remote-refs-for-fetch." ;;
+       1)
+           get_remote_default_refs_for_fetch "$@" ;;
+       *)
+           shift
+           tag_just_seen=
+           for ref
+           do
+               if test "$tag_just_seen"
+               then
+                   echo "refs/tags/${ref}:refs/tags/${ref}"
+                   tag_just_seen=
+                   continue
+               else
+                   case "$ref" in
+                   tag)
+                       tag_just_seen=yes
+                       continue
+                       ;;
+                   esac
+               fi
+               canon_refs_list_for_fetch "$ref"
+           done
+           ;;
+       esac
+}
index fc463260bd9dd07e50494e7cbb39ef6833179ff3..c31a65ca8c191b4b37784c7d398860baf3630cbc 100755 (executable)
@@ -1,12 +1,44 @@
 #!/bin/sh
 #
+# Copyright (c) 2005 Junio C Hamano
+#
+# Fetch one or more remote refs and merge it/them into the current HEAD.
+
 . git-sh-setup-script || die "Not a git archive"
-. git-parse-remote "$@"
-merge_name="$_remote_name"
 
-git-fetch-script "$@" || exit 1
+orig_head=$(cat "$GIT_DIR/HEAD") || die "Pulling into a black hole?"
+git-fetch-script --update-head-ok "$@" || exit 1
+
+curr_head=$(cat "$GIT_DIR/HEAD")
+if test "$curr_head" != "$orig_head"
+then
+       # The fetch involved updating the current branch.
+
+       # The working tree and the index file is still based on the
+       # $orig_head commit, but we are merging into $curr_head.
+       # First update the working tree to match $curr_head.
+
+       echo >&2 "Warning: fetch updated the current branch head."
+       echo >&2 "Warning: fast forwarding your working tree."
+       git-read-tree -u -m "$orig_head" "$curr_head" ||
+               die "You need to first update your working tree."
+fi
+
+merge_head=$(sed -e 's/        .*//' "$GIT_DIR"/FETCH_HEAD | tr '\012' ' ')
+merge_name=$(sed -e 's/^[0-9a-f]*      //' "$GIT_DIR"/FETCH_HEAD |
+        tr '\012' ' ')
+
+case "$merge_head" in
+'')
+       echo >&2 "No changes."
+       exit 0
+       ;;
+*' '?*)
+       echo >&2 "Pulling more than one heads; making an Octopus."
+       exec git-octopus-script
+       ;;
+esac
 
 git-resolve-script \
        "$(cat "$GIT_DIR"/HEAD)" \
-       "$(cat "$GIT_DIR"/FETCH_HEAD)" \
-       "Merge $merge_name"
+       $merge_head "Merge $merge_name"
index 70fa9684a51be3dbbcb83460c32bb8d7fe1b4cf0..744ee7e7dc8986767f410f99f4ff8c644654b172 100755 (executable)
@@ -20,36 +20,24 @@ do
        -*)
                die "Unknown parameter $1" ;;
         *)
-               remote="$1"
-               shift
                set x "$@"
                shift
                break ;;
        esac
        shift
 done
+case "$#" in
+0)
+       die "Where would you want to push today?" ;;
+esac
 
-case "$remote" in
-*:* | /* | ../* | ./* )
-       # An URL, host:/path/to/git, absolute and relative paths.
-       ;;
-* )
-       # Shorthand
-       if expr "$remote" : '..*/..*' >/dev/null
-       then
-               # a short-hand followed by a trailing path
-               shorthand=$(expr "$remote" : '\([^/]*\)')
-               remainder=$(expr "$remote" : '[^/]*\(/.*\)$')
-       else
-               shorthand="$remote"
-               remainder=
-       fi
-       remote=$(sed -e 's/#.*//' "$GIT_DIR/branches/$remote") &&
-       expr "$remote" : '..*:' >/dev/null &&
-       remote="$remote$remainder" ||
-       die "Cannot parse remote $remote"
-       ;;
+. git-parse-remote-script
+remote=$(get_remote_url "$@")
+case "$has_all" in
+--all) set x ;;
+'')    set x $(get_remote_refs_for_push "$@") ;;
 esac
+shift
 
 case "$remote" in
 http://* | https://* | git://* | rsync://* )
index 15b7fd6a15de3a3a5df6a7408f65410c37c0589e..1c9a6315dd63dd27462aa7ca10880f7d3cb663c2 100755 (executable)
@@ -1,6 +1,20 @@
 #!/bin/sh
+#
+# Copyright (c) 2005 Linus Torvalds
+#
+
 . git-sh-setup-script || die "Not a git archive"
        
+no_update_info=
+while case "$#" in 0) break ;; esac
+do
+       case "$1" in
+       -n)     no_update_info=t ;;
+       *)      break ;;
+       esac
+       shift
+done
+
 rm -f .tmp-pack-*
 packname=$(git-rev-list --unpacked --objects $(git-rev-parse --all) |
        git-pack-objects --non-empty --incremental .tmp-pack) ||
@@ -9,6 +23,11 @@ if [ -z "$packname" ]; then
        echo Nothing new to pack
        exit 0
 fi
+
 mkdir -p "$GIT_OBJECT_DIRECTORY/pack" &&
 mv .tmp-pack-$packname.pack "$GIT_OBJECT_DIRECTORY/pack/pack-$packname.pack" &&
-mv .tmp-pack-$packname.idx  "$GIT_OBJECT_DIRECTORY/pack/pack-$packname.idx"
+mv .tmp-pack-$packname.idx  "$GIT_OBJECT_DIRECTORY/pack/pack-$packname.idx" &&
+case "$no_update_info" in
+t) : ;;
+*) git-update-server-info ;;
+esac
index 919081522942a1817b669422f28e045a2849d866..ae6cd272bab01ba7fa9ac7378fe33e07e853d307 100755 (executable)
@@ -19,8 +19,8 @@ head=${3-HEAD}
 [ "$revision" ] || usage
 [ "$url" ] || usage
 
-baserev=`git-rev-parse --verify $revision^0` &&
-headrev=`git-rev-parse --verify $head^0` || exit
+baserev=`git-rev-parse --verify "$revision"^0` &&
+headrev=`git-rev-parse --verify "$head"^0` || exit
 
 echo "The following changes since commit $baserev:"
 git log --max-count=1 --pretty=short "$baserev" |
index 50d5f8336feec0eb9839a2641cb9faf9ab67391d..7c0e3d8aa8f7e63d1e98b79612844043a8481011 100755 (executable)
@@ -49,7 +49,41 @@ if [ "$common" == "$head" ]; then
        dropheads
        exit 0
 fi
-echo "Trying to merge $merge into $head"
+
+# Find an optimum merge base if there are more than one candidates.
+LF='
+'
+common=$(git-merge-base -a $head $merge)
+case "$common" in
+?*"$LF"?*)
+       echo "Trying to find the optimum merge base."
+       G=.tmp-index$$
+       best=
+       best_cnt=-1
+       for c in $common
+       do
+               rm -f $G
+               GIT_INDEX_FILE=$G git-read-tree -m $c $head $merge \
+                       2>/dev/null || continue
+               # Count the paths that are unmerged.
+               cnt=`GIT_INDEX_FILE=$G git-ls-files --unmerged | wc -l`
+               if test $best_cnt -le 0 -o $cnt -le $best_cnt
+               then
+                       best=$c
+                       best_cnt=$cnt
+                       if test "$best_cnt" -eq 0
+                       then
+                               # Cannot do any better than all trivial merge.
+                               break
+                       fi
+               fi
+       done
+       rm -f $G
+       common="$best"
+esac
+
+echo "Trying to merge $merge into $head using $common."
+git-update-cache --refresh 2>/dev/null
 git-read-tree -u -m $common $head $merge || exit 1
 result_tree=$(git-write-tree  2> /dev/null)
 if [ $? -ne 0 ]; then
index dc2dea48987dce1e266cdb8da2086293b4811d68..22f2082fb1d9612fdc41b0edd7ec90327cfcf004 100755 (executable)
@@ -10,7 +10,7 @@ case "$status" in
        die "Your working tree is dirty; cannot revert a previous patch." ;;
 esac
 
-rev=$(git-rev-parse --no-flags --verify --revs-only "$@") &&
+rev=$(git-rev-parse --verify "$@") &&
 commit=$(git-rev-parse --verify "$rev^0") || exit
 if git-diff-tree -R -M -p $commit | git-apply --index &&
    msg=$(git-rev-list --pretty=oneline --max-count=1 $commit)
index 5bf471f78150962a131ebc5f1b2e92e57cda70c9..84e15df1bcedba39e9310700d2aa7bf14dde2395 100755 (executable)
@@ -11,7 +11,6 @@ die() {
        exit 1
 }
 
-[ -d "$GIT_DIR" ] &&
+[ -h "$GIT_DIR/HEAD" ] &&
 [ -d "$GIT_DIR/refs" ] &&
-[ -d "$GIT_OBJECT_DIRECTORY" ] &&
 [ -d "$GIT_OBJECT_DIRECTORY/00" ]
index 947cc219752ce3f099ca182e32e684f09ab4c1db..1696f23e04a1b96234c60ae07306fdd94d0da314 100755 (executable)
@@ -1,4 +1,7 @@
 #!/bin/sh
+#
+# Copyright (c) 2005 Linus Torvalds
+#
 . git-sh-setup-script || die "Not a git archive"
 
 report () {
@@ -28,19 +31,43 @@ report () {
   [ "$header" ]
 }
 
+branch=`readlink "$GIT_DIR/HEAD"`
+case "$branch" in
+refs/heads/master) ;;
+*)     echo "# On branch $branch" ;;
+esac
+
 git-update-cache --refresh >/dev/null 2>&1
-git-diff-cache -M --cached HEAD | sed 's/^://' | report "Updated but not checked in" "will commit"
+
+git-diff-cache -M --cached HEAD |
+sed 's/^://' |
+report "Updated but not checked in" "will commit"
+
 committable="$?"
-git-diff-files | sed 's/^://' | report "Changed but not updated" "use git-update-cache to mark for commit"
+
+git-diff-files |
+sed 's/^://' |
+report "Changed but not updated" "use git-update-cache to mark for commit"
+
+if grep -v '^#' "$GIT_DIR/info/exclude" >/dev/null 2>&1
+then
+       git-ls-files --others \
+           --exclude-from="$GIT_DIR/info/exclude" \
+           --exclude-per-directory=.gitignore |
+       sed -e '
+       1i\
+#\
+# Ignored files:\
+#   (use "git add" to add to commit)\
+#
+       s/^/#   /
+       $a\
+#'
+fi
+
 if [ "$committable" == "0" ]
 then
        echo "nothing to commit"
        exit 1
 fi
-branch=`readlink "$GIT_DIR/HEAD"`
-case "$branch" in
-refs/heads/master) ;;
-*)     echo "#
-# On branch $branch" ;;
-esac
 exit 0
index 56f3919e069eb7390ff1f06ff25a0cc9c420e8a8..0d79104e0dd16c77c10a7db43c1afce3fc733160 100644 (file)
@@ -496,7 +496,7 @@ static void verify_pathspec(void)
                        char c = n[i];
                        if (prev && prev[i] != c)
                                break;
-                       if (c == '*' || c == '?')
+                       if (!c || c == '*' || c == '?')
                                break;
                        if (c == '/')
                                len = i+1;
index 923256c821582f38daffed4fb0df2a97fe66d74b..286bf0e8d1522ac4cf01f75343da40ddff6bf6e8 100644 (file)
@@ -82,13 +82,17 @@ static struct commit *interesting(struct commit_list *list)
  * commit B.
  */
 
-static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
+static int show_all = 0;
+
+static int merge_base(struct commit *rev1, struct commit *rev2)
 {
        struct commit_list *list = NULL;
        struct commit_list *result = NULL;
 
-       if (rev1 == rev2)
-               return rev1;
+       if (rev1 == rev2) {
+               printf("%s\n", sha1_to_hex(rev1->object.sha1));
+               return 0;
+       }
 
        parse_commit(rev1);
        parse_commit(rev2);
@@ -108,7 +112,7 @@ static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
                if (flags == 3) {
                        insert_by_date(commit, &result);
 
-                       /* Mark children of a found merge uninteresting */
+                       /* Mark parents of a found merge uninteresting */
                        flags |= UNINTERESTING;
                }
                parents = commit->parents;
@@ -122,26 +126,46 @@ static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
                        insert_by_date(p, &list);
                }
        }
-       return interesting(result);
+
+       if (!result)
+               return 1;
+
+       while (result) {
+               struct commit *commit = result->item;
+               result = result->next;
+               if (commit->object.flags & UNINTERESTING)
+                       continue;
+               printf("%s\n", sha1_to_hex(commit->object.sha1));
+               if (!show_all)
+                       return 0;
+               commit->object.flags |= UNINTERESTING;
+       }
+       return 0;
 }
 
+static const char merge_base_usage[] =
+"git-merge-base [--all] <commit-id> <commit-id>";
+
 int main(int argc, char **argv)
 {
-       struct commit *rev1, *rev2, *ret;
+       struct commit *rev1, *rev2;
        unsigned char rev1key[20], rev2key[20];
 
+       while (1 < argc && argv[1][0] == '-') {
+               char *arg = argv[1];
+               if (!strcmp(arg, "-a") || !strcmp(arg, "--all"))
+                       show_all = 1;
+               else
+                       usage(merge_base_usage);
+               argc--; argv++;
+       }
        if (argc != 3 ||
            get_sha1(argv[1], rev1key) ||
-           get_sha1(argv[2], rev2key)) {
-               usage("git-merge-base <commit-id> <commit-id>");
-       }
+           get_sha1(argv[2], rev2key))
+               usage(merge_base_usage);
        rev1 = lookup_commit_reference(rev1key);
        rev2 = lookup_commit_reference(rev2key);
        if (!rev1 || !rev2)
                return 1;
-       ret = common_ancestor(rev1, rev2);
-       if (!ret)
-               return 1;
-       printf("%s\n", sha1_to_hex(ret->object.sha1));
-       return 0;
+       return merge_base(rev1, rev2);
 }
index 3643adb631d550a0ae225a5cfc53cb34330199f3..2d97cdb64bdad56046c1dfd2fd784af54d420ca5 100644 (file)
@@ -33,7 +33,7 @@ static int blob_objects = 0;
 static int verbose_header = 0;
 static int show_parents = 0;
 static int hdr_termination = 0;
-static const char *prefix = "";
+static const char *commit_prefix = "";
 static unsigned long max_age = -1;
 static unsigned long min_age = -1;
 static int max_count = -1;
@@ -48,14 +48,14 @@ static void show_commit(struct commit *commit)
 {
        commit->object.flags |= SHOWN;
        if (show_breaks) {
-               prefix = "| ";
+               commit_prefix = "| ";
                if (commit->object.flags & DISCONTINUITY) {
-                       prefix = "^ ";     
+                       commit_prefix = "^ ";     
                } else if (commit->object.flags & BOUNDARY) {
-                       prefix = "= ";
+                       commit_prefix = "= ";
                } 
         }                      
-       printf("%s%s", prefix, sha1_to_hex(commit->object.sha1));
+       printf("%s%s", commit_prefix, sha1_to_hex(commit->object.sha1));
        if (show_parents) {
                struct commit_list *parents = commit->parents;
                while (parents) {
@@ -481,9 +481,9 @@ static void handle_one_commit(struct commit *com, struct commit_list **lst)
 int main(int argc, char **argv)
 {
        struct commit_list *list = NULL;
-       const char *prefix = setup_git_directory();
        int i, limited = 0;
 
+       setup_git_directory();
        for (i = 1 ; i < argc; i++) {
                int flags;
                char *arg = argv[i];
@@ -511,9 +511,9 @@ int main(int argc, char **argv)
                        verbose_header = 1;
                        hdr_termination = '\n';
                        if (commit_format == CMIT_FMT_ONELINE)
-                               prefix = "";
+                               commit_prefix = "";
                        else
-                               prefix = "commit ";
+                               commit_prefix = "commit ";
                        continue;
                }
                if (!strncmp(arg, "--no-merges", 11)) {
index 9281b45d1f54dda858d7adff14e90f8e94eccc13..6d723f902aaff806431d5e47916dadba7af18a37 100644 (file)
@@ -7,20 +7,21 @@
 #include "commit.h"
 #include "refs.h"
 
+#define DO_REVS                1
+#define DO_NOREV       2
+#define DO_FLAGS       4
+#define DO_NONFLAGS    8
+static int filter = ~0;
+
 static char *def = NULL;
-static int no_revs = 0;
-static int single_rev = 0;
-static int revs_only = 0;
-static int do_rev_argument = 1;
-static int output_revs = 0;
-static int flags_only = 0;
-static int no_flags = 0;
-static int output_sq = 0;
-static int symbolic = 0;
 
 #define NORMAL 0
 #define REVERSED 1
 static int show_type = NORMAL;
+static int symbolic = 0;
+static int output_sq = 0;
+
+static int revs_count = 0;
 
 /*
  * Some arguments are relevant "revision" arguments,
@@ -30,13 +31,19 @@ static int show_type = NORMAL;
 static int is_rev_argument(const char *arg)
 {
        static const char *rev_args[] = {
-               "--max-count=",
+               "--bisect",
+               "--header",
                "--max-age=",
-               "--min-age=",
+               "--max-count=",
                "--merge-order",
-               "--topo-order",
-               "--bisect",
+               "--min-age=",
                "--no-merges",
+               "--objects",
+               "--parents",
+               "--pretty",
+               "--show-breaks",
+               "--topo-order",
+               "--unpacked",
                NULL
        };
        const char **p = rev_args;
@@ -47,11 +54,13 @@ static int is_rev_argument(const char *arg)
                if (!str)
                        return 0;
                len = strlen(str);
-               if (!strncmp(arg, str, len))
+               if (!strcmp(arg, str) ||
+                   (str[len-1] == '=' && !strncmp(arg, str, len)))
                        return 1;
        }
 }
 
+/* Output argument as a string, either SQ or normal */
 static void show(const char *arg)
 {
        if (output_sq) {
@@ -70,11 +79,13 @@ static void show(const char *arg)
                puts(arg);
 }
 
+/* Output a revision, only if filter allows it */
 static void show_rev(int type, const unsigned char *sha1, const char *name)
 {
-       if (no_revs)
+       if (!(filter & DO_REVS))
                return;
-       output_revs++;
+       def = NULL;
+       revs_count++;
 
        if (type != show_type)
                putchar('^');
@@ -84,29 +95,12 @@ static void show_rev(int type, const unsigned char *sha1, const char *name)
                show(sha1_to_hex(sha1));
 }
 
-static void show_rev_arg(char *rev)
+/* Output a flag, only if filter allows it. */
+static void show_flag(char *arg)
 {
-       if (no_revs)
+       if (!(filter & DO_FLAGS))
                return;
-       show(rev);
-}
-
-static void show_norev(char *norev)
-{
-       if (flags_only)
-               return;
-       if (revs_only)
-               return;
-       show(norev);
-}
-
-static void show_arg(char *arg)
-{
-       if (no_flags)
-               return;
-       if (do_rev_argument && is_rev_argument(arg))
-               show_rev_arg(arg);
-       else
+       if (filter & (is_rev_argument(arg) ? DO_REVS : DO_NOREV))
                show(arg);
 }
 
@@ -122,7 +116,6 @@ static void show_default(void)
                        show_rev(NORMAL, sha1, s);
                        return;
                }
-               show_norev(s);
        }
 }
 
@@ -134,7 +127,7 @@ static int show_reference(const char *refname, const unsigned char *sha1)
 
 int main(int argc, char **argv)
 {
-       int i, as_is = 0;
+       int i, as_is = 0, verify = 0;
        unsigned char sha1[20];
        const char *prefix = setup_git_directory();
        
@@ -143,15 +136,13 @@ int main(int argc, char **argv)
                char *dotdot;
        
                if (as_is) {
-                       show_norev(arg);
+                       show(arg);
                        continue;
                }
                if (*arg == '-') {
                        if (!strcmp(arg, "--")) {
-                               show_default();
-                               if (revs_only || flags_only)
-                                       break;
                                as_is = 1;
+                               continue;
                        }
                        if (!strcmp(arg, "--default")) {
                                def = argv[i+1];
@@ -159,25 +150,24 @@ int main(int argc, char **argv)
                                continue;
                        }
                        if (!strcmp(arg, "--revs-only")) {
-                               revs_only = 1;
+                               filter &= ~DO_NOREV;
                                continue;
                        }
                        if (!strcmp(arg, "--no-revs")) {
-                               no_revs = 1;
+                               filter &= ~DO_REVS;
                                continue;
                        }
                        if (!strcmp(arg, "--flags")) {
-                               flags_only = 1;
+                               filter &= ~DO_NONFLAGS;
                                continue;
                        }
                        if (!strcmp(arg, "--no-flags")) {
-                               no_flags = 1;
+                               filter &= ~DO_FLAGS;
                                continue;
                        }
                        if (!strcmp(arg, "--verify")) {
-                               revs_only = 1;
-                               do_rev_argument = 0;
-                               single_rev = 1;
+                               filter &= ~(DO_FLAGS|DO_NOREV);
+                               verify = 1;
                                continue;
                        }
                        if (!strcmp(arg, "--sq")) {
@@ -197,12 +187,17 @@ int main(int argc, char **argv)
                                continue;
                        }
                        if (!strcmp(arg, "--show-prefix")) {
-                               puts(prefix);
+                               if (prefix)
+                                       puts(prefix);
                                continue;
                        }
-                       show_arg(arg);
+                       if (verify)
+                               die("Needed a single revision");
+                       show_flag(arg);
                        continue;
                }
+
+               /* Not a flag argument */
                dotdot = strstr(arg, "..");
                if (dotdot) {
                        unsigned char end[20];
@@ -212,9 +207,6 @@ int main(int argc, char **argv)
                                if (!*n)
                                        n = "HEAD";
                                if (!get_sha1(n, end)) {
-                                       if (no_revs)
-                                               continue;
-                                       def = NULL;
                                        show_rev(NORMAL, end, n);
                                        show_rev(REVERSED, sha1, arg);
                                        continue;
@@ -223,26 +215,21 @@ int main(int argc, char **argv)
                        *dotdot = '.';
                }
                if (!get_sha1(arg, sha1)) {
-                       if (no_revs)
-                               continue;
-                       def = NULL;
                        show_rev(NORMAL, sha1, arg);
                        continue;
                }
                if (*arg == '^' && !get_sha1(arg+1, sha1)) {
-                       if (no_revs)
-                               continue;
-                       def = NULL;
                        show_rev(REVERSED, sha1, arg+1);
                        continue;
                }
-               show_default();
-               show_norev(arg);
+               if (verify)
+                       die("Needed a single revision");
+               if ((filter & (DO_NONFLAGS|DO_NOREV)) ==
+                   (DO_NONFLAGS|DO_NOREV))
+                       show(arg);
        }
        show_default();
-       if (single_rev && output_revs != 1) {
-               fprintf(stderr, "Needed a single revision\n");
-               exit(1);
-       }
+       if (verify && revs_count != 1)
+               die("Needed a single revision");
        return 0;
 }
index 0ab135c9881c4d9fa6b82ea80f5e62d2fbf17d28..55d8ff7e102fa6cc369c993035c0579c2d33b775 100644 (file)
@@ -206,7 +206,8 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
                /* This part determines what can overwrite what.
                 * The rules are:
                 *
-                * (0) you can always use --force.
+                * (0) you can always use --force or +A:B notation to
+                *     selectively force individual ref pairs.
                 *
                 * (1) if the old thing does not exist, it is OK.
                 *
@@ -218,16 +219,19 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
                 *     descendant of old, it is OK.
                 */
 
-               if (!force_update && !is_zero_sha1(ref->old_sha1)) {
+               if (!force_update &&
+                   !is_zero_sha1(ref->old_sha1) &&
+                   !ref->force) {
                        if (!has_sha1_file(ref->old_sha1)) {
                                error("remote '%s' object %s does not "
                                      "exist on local",
                                      ref->name, sha1_to_hex(ref->old_sha1));
                                continue;
                        }
+
                        /* We assume that local is fsck-clean.  Otherwise
-                        * you _could_ have a old tag which points at
-                        * something you do not have which may or may not
+                        * you _could_ have an old tag which points at
+                        * something you do not have, which may or may not
                         * be a commit.
                         */
                        if (!ref_newer(ref->peer_ref->new_sha1,
diff --git a/setup.c b/setup.c
index b8789de5c523d72110187960fb887852732f8486..258da176150081749a2ca2faeebc316911f0fba1 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -72,6 +72,24 @@ const char **get_pathspec(const char *prefix, char **pathspec)
        return (const char **) pathspec;
 }
 
+/*
+ * Test it it looks like we're at the top
+ * level git directory. We want to see a
+ *
+ *  - a HEAD symlink and a refs/ directory under ".git"
+ *  - either a .git/objects/ directory _or_ the proper
+ *    GIT_OBJECT_DIRECTORY environment variable
+ */
+static int is_toplevel_directory(void)
+{
+       struct stat st;
+
+       return  !lstat(".git/HEAD", &st) &&
+               S_ISLNK(st.st_mode) &&
+               !access(".git/refs/", X_OK) &&
+               (gitenv(DB_ENVIRONMENT) || !access(".git/objects/", X_OK));
+}
+
 const char *setup_git_directory(void)
 {
        static char cwd[PATH_MAX+1];
@@ -89,17 +107,8 @@ const char *setup_git_directory(void)
 
        offset = len = strlen(cwd);
        for (;;) {
-               /*
-                * We always want to see a .git/refs/ subdirectory
-                */
-               if (!access(".git/refs/", X_OK)) {
-                       /*
-                        * Then we need either a GIT_OBJECT_DIRECTORY define
-                        * or a .git/objects/ directory
-                        */
-                       if (gitenv(DB_ENVIRONMENT) || !access(".git/objects/", X_OK))
-                               break;
-               }
+               if (is_toplevel_directory())
+                       break;
                chdir("..");
                do {
                        if (!offset)
index fc827ee4972254661f5fc09cb7f8890b1d007646..2a4e1768adc88e25dc108d6c9b323da2c52f5b1c 100644 (file)
@@ -141,6 +141,18 @@ static void show_one_commit(struct commit *commit, char **head_name)
 static char *ref_name[MAX_REVS + 1];
 static int ref_name_cnt;
 
+static int compare_ref_name(const void *a_, const void *b_)
+{
+       const char * const*a = a_, * const*b = b_;
+       return strcmp(*a, *b);
+}
+
+static void sort_ref_range(int bottom, int top)
+{
+       qsort(ref_name + bottom, top - bottom, sizeof(ref_name[0]),
+             compare_ref_name);
+}
+
 static int append_ref(const char *refname, const unsigned char *sha1)
 {
        struct commit *commit = lookup_commit_reference_gently(sha1, 1);
@@ -161,7 +173,7 @@ static int append_head_ref(const char *refname, const unsigned char *sha1)
 {
        if (strncmp(refname, "refs/heads/", 11))
                return 0;
-       return append_ref(refname + 5, sha1);
+       return append_ref(refname + 11, sha1);
 }
 
 static int append_tag_ref(const char *refname, const unsigned char *sha1)
@@ -173,10 +185,16 @@ static int append_tag_ref(const char *refname, const unsigned char *sha1)
 
 static void snarf_refs(int head, int tag)
 {
-       if (head)
+       if (head) {
+               int orig_cnt = ref_name_cnt;
                for_each_ref(append_head_ref);
-       if (tag)
+               sort_ref_range(orig_cnt, ref_name_cnt);
+       }
+       if (tag) {
+               int orig_cnt = ref_name_cnt;
                for_each_ref(append_tag_ref);
+               sort_ref_range(orig_cnt, ref_name_cnt);
+       }
 }
 
 static int rev_is_head(char *head_path, int headlen,
diff --git a/t/t4109-apply-multifrag.sh b/t/t4109-apply-multifrag.sh
new file mode 100644 (file)
index 0000000..5988e1a
--- /dev/null
@@ -0,0 +1,176 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+# Copyright (c) 2005 Robert Fitzsimons
+#
+
+test_description='git-apply test patches with multiple fragments.
+
+'
+. ./test-lib.sh
+
+# setup
+
+cat > patch1.patch <<\EOF
+diff --git a/main.c b/main.c
+new file mode 100644
+--- /dev/null
++++ b/main.c
+@@ -0,0 +1,23 @@
++#include <stdio.h>
++
++int func(int num);
++void print_int(int num);
++
++int main() {
++      int i;
++
++      for (i = 0; i < 10; i++) {
++              print_int(func(i));
++      }
++
++      return 0;
++}
++
++int func(int num) {
++      return num * num;
++}
++
++void print_int(int num) {
++      printf("%d", num);
++}
++
+EOF
+cat > patch2.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,7 +1,9 @@
++#include <stdlib.h>
+ #include <stdio.h>
+ int func(int num);
+ void print_int(int num);
++void print_ln();
+ int main() {
+       int i;
+@@ -10,6 +12,8 @@
+               print_int(func(i));
+       }
++      print_ln();
++
+       return 0;
+ }
+@@ -21,3 +25,7 @@
+       printf("%d", num);
+ }
++void print_ln() {
++      printf("\n");
++}
++
+EOF
+cat > patch3.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,9 +1,7 @@
+-#include <stdlib.h>
+ #include <stdio.h>
+ int func(int num);
+ void print_int(int num);
+-void print_ln();
+ int main() {
+       int i;
+@@ -12,8 +10,6 @@
+               print_int(func(i));
+       }
+-      print_ln();
+-
+       return 0;
+ }
+@@ -25,7 +21,3 @@
+       printf("%d", num);
+ }
+-void print_ln() {
+-      printf("\n");
+-}
+-
+EOF
+cat > patch4.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,13 +1,14 @@
+ #include <stdio.h>
+ int func(int num);
+-void print_int(int num);
++int func2(int num);
+ int main() {
+       int i;
+       for (i = 0; i < 10; i++) {
+-              print_int(func(i));
++              printf("%d", func(i));
++              printf("%d", func3(i));
+       }
+       return 0;
+@@ -17,7 +18,7 @@
+       return num * num;
+ }
+-void print_int(int num) {
+-      printf("%d", num);
++int func2(int num) {
++      return num * num * num;
+ }
+EOF
+
+test_expect_success "S = git-apply (1)" \
+    'git-apply patch1.patch patch2.patch'
+mv main.c main.c.git
+
+test_expect_success "S = patch (1)" \
+    'cat patch1.patch patch2.patch | patch -p1'
+
+test_expect_success "S = cmp (1)" \
+    'cmp main.c.git main.c'
+
+rm -f main.c main.c.git
+
+test_expect_success "S = git-apply (2)" \
+    'git-apply patch1.patch patch2.patch patch3.patch'
+mv main.c main.c.git
+
+test_expect_success "S = patch (2)" \
+    'cat patch1.patch patch2.patch patch3.patch | patch -p1'
+
+test_expect_success "S = cmp (2)" \
+    'cmp main.c.git main.c'
+
+rm -f main.c main.c.git
+
+test_expect_success "S = git-apply (3)" \
+    'git-apply patch1.patch patch4.patch'
+mv main.c main.c.git
+
+test_expect_success "S = patch (3)" \
+    'cat patch1.patch patch4.patch | patch -p1'
+
+test_expect_success "S = cmp (3)" \
+    'cmp main.c.git main.c'
+
+test_done
+
diff --git a/t/t4110-apply-scan.sh b/t/t4110-apply-scan.sh
new file mode 100644 (file)
index 0000000..005f744
--- /dev/null
@@ -0,0 +1,101 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+# Copyright (c) 2005 Robert Fitzsimons
+#
+
+test_description='git-apply test for patches which require scanning forwards and backwards.
+
+'
+. ./test-lib.sh
+
+# setup
+
+cat > patch1.patch <<\EOF
+diff --git a/new.txt b/new.txt
+new file mode 100644
+--- /dev/null
++++ b/new.txt
+@@ -0,0 +1,12 @@
++a1
++a11
++a111
++a1111
++b1
++b11
++b111
++b1111
++c1
++c11
++c111
++c1111
+EOF
+cat > patch2.patch <<\EOF
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -1,7 +1,3 @@
+-a1
+-a11
+-a111
+-a1111
+ b1
+ b11
+ b111
+EOF
+cat > patch3.patch <<\EOF
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -6,6 +6,10 @@
+ b11
+ b111
+ b1111
++b2
++b22
++b222
++b2222
+ c1
+ c11
+ c111
+EOF
+cat > patch4.patch <<\EOF
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -1,3 +1,7 @@
++a1
++a11
++a111
++a1111
+ b1
+ b11
+ b111
+EOF
+cat > patch5.patch <<\EOF
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -10,3 +10,7 @@
+ c11
+ c111
+ c1111
++c2
++c22
++c222
++c2222
+EOF
+
+test_expect_success "S = git-apply scan" \
+    'git-apply patch1.patch patch2.patch patch3.patch patch4.patch patch5.patch'
+mv new.txt apply.txt
+
+test_expect_success "S = patch scan" \
+    'cat patch1.patch patch2.patch patch3.patch patch4.patch patch5.patch | patch'
+mv new.txt patch.txt
+
+test_expect_success "S = cmp" \
+    'cmp apply.txt patch.txt'
+
+test_done
+
diff --git a/templates/.gitignore b/templates/.gitignore
new file mode 100644 (file)
index 0000000..ca680c5
--- /dev/null
@@ -0,0 +1 @@
+blt
diff --git a/templates/remotes-- b/templates/remotes--
new file mode 100644 (file)
index 0000000..fae8870
--- /dev/null
@@ -0,0 +1 @@
+: this is just to ensure the directory exists.
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644 (file)
index 0000000..d1ea9ea
--- /dev/null
@@ -0,0 +1,2 @@
+git-mailinfo
+git-mailsplit