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 91added..bd6833b 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 6121e90..fd9881f 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 866d9c2..3001143 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 fe9a041..3ace8ad 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 14d0bd5..9ff7bc2 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 2543617..8a3cedf 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 db3086c..d15222b 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 617276a..789d3a9 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 9a4abd1..b6fa2a8 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 ad9d3ab..8111813 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 3c1208d..556682f 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 ba7cbb7..8f14186 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 4c2b435..99c05d4 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 99c399a..77076aa 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 8a532e6..727073e 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 6192c5d..5ed25f5 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 92addd7..5ac613a 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 fc87146..d1a550c 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 88a2646..d5d747c 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 55d63d9..f63cbdd 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 7456cff..a069b7b 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 ae90941..132d5ec 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 8299ca5..6cc1c79 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 8109b7f..f627e42 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 52fa4c0..b3b4d2c 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 7ae4ba0..8f6b68c 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 876a4af..866dbbe 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 ac4f211..c0fdaa7 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 ee59be6..e87190e 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 e4f4664..d407f39 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 c0bf869..825c439 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 2788cdd..5b7b4d3 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 5df89dd..6735a0d 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 f1bbea8..1ed4633 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 3801e75..e54f897 100644 (file)
@@ -1 +1,3 @@
 /usr/bin/gitk
+/usr/share/man/man1/gitk.*
+/usr/share/doc/git-core/gitk.*
index c46b4d9..86464bf 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 29b25f4..0c5c107 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 a6dfeaf..0ecbd23 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 a377407..9feff14 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 99c2459..f988b8c 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 5c5f564..4987e37 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 ea09714..dd94ede 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 9260f92..5716b29 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 75f6027..061a231 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 fc46326..c31a65c 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 70fa968..744ee7e 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 15b7fd6..1c9a631 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 9190815..ae6cd27 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 50d5f83..7c0e3d8 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 dc2dea4..22f2082 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 5bf471f..84e15df 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 947cc21..1696f23 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 56f3919..0d79104 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 923256c..286bf0e 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 3643adb..2d97cdb 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 9281b45..6d723f9 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 0ab135c..55d8ff7 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 b8789de..258da17 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 fc827ee..2a4e176 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