Merge branch 'sb/maint-pull-rebase' into maint
authorJunio C Hamano <gitster@pobox.com>
Fri, 21 Aug 2009 18:33:08 +0000 (11:33 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 21 Aug 2009 18:33:08 +0000 (11:33 -0700)
* sb/maint-pull-rebase:
pull: support rebased upstream + fetch + pull --rebase
t5520-pull: Test for rebased upstream + fetch + pull --rebase

88 files changed:
Documentation/Makefile
Documentation/RelNotes-1.6.3.4.txt [new file with mode: 0644]
Documentation/RelNotes-1.6.4.txt
Documentation/config.txt
Documentation/diff-format.txt
Documentation/fetch-options.txt
Documentation/git-add.txt
Documentation/git-clone.txt
Documentation/git-diff-files.txt
Documentation/git-diff-index.txt
Documentation/git-diff-tree.txt
Documentation/git-diff.txt
Documentation/git-fast-export.txt
Documentation/git-filter-branch.txt
Documentation/git-format-patch.txt
Documentation/git-merge.txt
Documentation/git-pack-objects.txt
Documentation/git-push.txt
Documentation/git-remote.txt
Documentation/git-rerere.txt
Documentation/git-rev-list.txt
Documentation/git-send-email.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/git-symbolic-ref.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/gitcore-tutorial.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
builtin-branch.c
builtin-fast-export.c
builtin-pack-objects.c
builtin-push.c
builtin-reflog.c
builtin-verify-pack.c
cache.h
combine-diff.c
commit.c
config.c
config.mak.in
configure.ac
contrib/completion/git-completion.bash
contrib/hg-to-git/hg-to-git.py
environment.c
git-compat-util.h
git-filter-branch.sh
git-instaweb.sh
git-rebase--interactive.sh
git-repack.sh
git-request-pull.sh
git-send-email.perl
git-stash.sh
git-svn.perl
gitweb/README
graph.c
help.c
pack-revindex.c
preload-index.c
refs.c
sha1_file.c
sha1_name.c
t/t1300-repo-config.sh
t/t3414-rebase-preserve-onto.sh [new file with mode: 0755]
t/t4038-diff-combined.sh [new file with mode: 0755]
t/t4124-apply-ws-rule.sh
t/t4202-log.sh
t/t5510-fetch.sh
t/t7700-repack.sh
t/t8005-blame-i18n.sh
t/t8005/euc-japan.txt [new file with mode: 0644]
t/t8005/sjis.txt
t/t8005/utf8.txt
t/t9138-git-svn-multiple-branches.sh [deleted file]
t/t9139-git-svn-reset.sh [deleted file]
t/t9140-git-svn-reset.sh [new file with mode: 0755]
t/t9141-git-svn-multiple-branches.sh [new file with mode: 0755]
t/t9142-git-svn-shallow-clone.sh [new file with mode: 0755]
t/t9143-git-svn-gc.sh [new file with mode: 0755]
t/t9200-git-cvsexportcommit.sh
t/t9301-fast-export.sh
transport.c
transport.h
unpack-trees.c
walker.c
ws.c
xdiff/xdiffi.c
index 7a8037f586773c00004e34079b48bb514db2515f..06b0c57b95057b3df4f215f3191fd8e9fc473e6f 100644 (file)
@@ -84,7 +84,7 @@ endif
 #
 
 ifdef ASCIIDOC8
-ASCIIDOC_EXTRA += -a asciidoc7compatible
+ASCIIDOC_EXTRA += -a asciidoc7compatible -a no-inline-literal
 endif
 ifdef DOCBOOK_XSL_172
 ASCIIDOC_EXTRA += -a git-asciidoc-no-roff
diff --git a/Documentation/RelNotes-1.6.3.4.txt b/Documentation/RelNotes-1.6.3.4.txt
new file mode 100644 (file)
index 0000000..cad461b
--- /dev/null
@@ -0,0 +1,36 @@
+GIT v1.6.3.4 Release Notes
+==========================
+
+Fixes since v1.6.3.3
+--------------------
+
+ * "git add --no-ignore-errors" did not override configured
+   add.ignore-errors configuration.
+
+ * "git apply --whitespace=fix" did not fix trailing whitespace on an
+   incomplete line.
+
+ * "git branch" opened too many commit objects unnecessarily.
+
+ * "git checkout -f $commit" with a path that is a file (or a symlink) in
+   the work tree to a commit that has a directory at the path issued an
+   unnecessary error message.
+
+ * "git diff -c/--cc" was very inefficient in coalescing the removed lines
+   shared between parents.
+
+ * "git diff -c/--cc" showed removed lines at the beginning of a file
+   incorrectly.
+
+ * "git remote show nickname" did not honor configured
+   remote.nickname.uploadpack when inspecting the branches at the remote.
+
+ * "git request-pull" when talking to the terminal for a preview
+   showed some of the output in the pager.
+
+ * "git request-pull start nickname [end]" did not honor configured
+   remote.nickname.uploadpack when it ran git-ls-remote against the remote
+   repository to learn the current tip of branches.
+
+Includes other documentation updates and minor fixes.
+
index af68297af537b2e4cbd4d4bcbe94cb382486fa05..7a904419f7815094b68c864a558624667d5a91d1 100644 (file)
@@ -22,13 +22,6 @@ branch pointed at by its HEAD, gets a large warning.  You can choose what
 should happen upon such a push by setting the configuration variable
 receive.denyDeleteCurrent in the receiving repository.
 
-When the user does not tell "git push" what to push, it has always
-pushed matching refs.  For some people it is unexpected, and a new
-configuration variable push.default has been introduced to allow
-changing a different default behaviour.  To advertise the new feature,
-a big warning is issued if this is not configured and a git push without
-arguments is attempted.
-
 
 Updates since v1.6.3
 --------------------
@@ -38,26 +31,67 @@ Updates since v1.6.3
  * gitweb Perl style clean-up.
 
  * git-svn updates, including a new --authors-prog option to map author
-   names by invoking an external program.
+   names by invoking an external program, 'git svn reset' to unwind
+   'git svn fetch', support for more than one branches, documenting
+   of the useful --minimize-url feature, new "git svn gc" command, etc.
 
 (portability)
 
  * We feed iconv with "UTF-8" instead of "utf8"; the former is
-   understood more widely.
+   understood more widely.  Similarly updated test scripts to use
+   encoding names more widely understood (e.g. use "ISO8859-1" instead
+   of "ISO-8859-1").
+
+ * Various portability fixes/workarounds for different vintages of
+   SunOS, IRIX, and Windows.
+
+ * Git-over-ssh transport on Windows supports PuTTY plink and TortoisePlink.
 
 (performance)
 
+ * Many repeated use of lstat() are optimized out in "checkout" codepath.
+
+ * git-status (and underlying git-diff-index --cached) are optimized
+   to take advantage of cache-tree information in the index.
+
 (usability, bells and whistles)
 
  * "git add --edit" lets users edit the whole patch text to fine-tune what
    is added to the index.
 
- * "git log --graph" draws graphs more compactly by using horizonal lines
+ * "git am" accepts StGIT series file as its input.
+
+ * "git bisect skip" skips to a more randomly chosen place in the hope
+   to avoid testing a commit that is too close to a commit that is
+   already known to be untestable.
+
+ * "git cvsexportcommit" learned -k option to stop CVS keywords expansion
+
+ * "git fast-export" learned to handle history simplification more
+   gracefully.
+
+ * "git fast-export" learned an option --tag-of-filtered-object to handle
+   dangling tags resulting from history simplification more usefully.
+
+ * "git grep" learned -p option to show the location of the match using the
+   same context hunk marker "git diff" uses.
+
+ * https transport can optionally be told that the used client
+   certificate is password protected, in which case it asks the
+   password only once.
+
+ * "git imap-send" is IPv6 aware.
+
+ * "git log --graph" draws graphs more compactly by using horizontal lines
    when able.
 
  * "git log --decorate" shows shorter refnames by stripping well-known
    refs/* prefix.
 
+ * "git push $name" honors remote.$name.pushurl if present before
+   using remote.$name.url.  In other words, the URL used for fetching
+   and pushing can be different.
+
  * "git send-email" understands quoted aliases in .mailrc files (might
    have to be backported to 1.6.3.X).
 
@@ -69,10 +103,17 @@ Updates since v1.6.3
  * "add" and "update" subcommands to "git submodule" learned --reference
    option to use local clone with references.
 
+ * "git submodule update" learned --rebase option to update checked
+   out submodules by rebasing the local changes.
+
+ * "gitweb" can optionally use gravatar to adorn author/committer names.
+
 (developers)
 
  * A major part of the "git bisect" wrapper has moved to C.
 
+ * Formatting with the new version of AsciiDoc 8.4.1 is now supported.
+
 Fixes since v1.6.3
 ------------------
 
@@ -82,12 +123,25 @@ release, unless otherwise noted.
 Here are fixes that this release has, but have not been backported to
 v1.6.3.X series.
 
+ * "git diff-tree -r -t" used to omit new or removed directories from
+   the output.  df533f3 (diff-tree -r -t: include added/removed
+   directories in the output, 2009-06-13) may need to be cherry-picked
+   to backport this fix.
+
  * The way Git.pm sets up a Repository object was not friendly to callers
    that chdir around.  It now internally records the repository location
    as an absolute path when autodetected.
 
----
-exec >/var/tmp/1
-echo O=$(git describe master)
-O=v1.6.3.1-168-g23807fa
-git shortlog --no-merges $O..master ^maint
+ * Removing a section with "git config --remove-section", when its
+   section header has a variable definition on the same line, lost
+   that variable definition.
+
+ * "git rebase -p --onto" used to always leave side branches of a merge
+   intact, even when both branches are subject to rewriting.
+
+ * "git repack" used to faithfully follow grafts and considered true
+   parents recorded in the commit object unreachable from the commit.
+   After such a repacking, you cannot remove grafts without corrupting
+   the repository.
+
+ * "git send-email" did not detect erroneous loops in alias expansion.
index cb6832b4e80efc7dc34690f92c63ba4ee12529c7..e94a8ab746293f47046babe4ed48201e8016f0ee 100644 (file)
@@ -49,7 +49,8 @@ There is also a case insensitive alternative `[section.subsection]` syntax.
 In this syntax, subsection names follow the same restrictions as for section
 names.
 
-All the other lines are recognized as setting variables, in the form
+All the other lines (and the remainder of the line after the section
+header) are recognized as setting variables, in the form
 'name = value'.  If there is no equal sign on the line, the entire line
 is taken as 'name' and the variable is recognized as boolean "true".
 The variable names are case-insensitive and only alphanumeric
@@ -604,7 +605,7 @@ color.interactive.<slot>::
        Use customized color for 'git-add --interactive'
        output. `<slot>` may be `prompt`, `header`, `help` or `error`, for
        four distinct types of normal output from interactive
-       programs.  The values of these variables may be specified as
+       commands.  The values of these variables may be specified as
        in color.branch.<slot>.
 
 color.pager::
@@ -1112,7 +1113,7 @@ instaweb.port::
        linkgit:git-instaweb[1].
 
 interactive.singlekey::
-       In interactive programs, allow the user to provide one-letter
+       In interactive commands, allow the user to provide one-letter
        input with a single key (i.e., without hitting enter).
        Currently this is used only by the `\--patch` mode of
        linkgit:git-add[1].  Note that this setting is silently
@@ -1387,6 +1388,50 @@ rerere.enabled::
        default enabled if you create `rr-cache` directory under
        `$GIT_DIR`, but can be disabled by setting this option to false.
 
+sendemail.identity::
+       A configuration identity. When given, causes values in the
+       'sendemail.<identity>' subsection to take precedence over
+       values in the 'sendemail' section. The default identity is
+       the value of 'sendemail.identity'.
+
+sendemail.smtpencryption::
+       See linkgit:git-send-email[1] for description.  Note that this
+       setting is not subject to the 'identity' mechanism.
+
+sendemail.smtpssl::
+       Deprecated alias for 'sendemail.smtpencryption = ssl'.
+
+sendemail.<identity>.*::
+       Identity-specific versions of the 'sendemail.*' parameters
+       found below, taking precedence over those when the this
+       identity is selected, through command-line or
+       'sendemail.identity'.
+
+sendemail.aliasesfile::
+sendemail.aliasfiletype::
+sendemail.bcc::
+sendemail.cc::
+sendemail.cccmd::
+sendemail.chainreplyto::
+sendemail.confirm::
+sendemail.envelopesender::
+sendemail.from::
+sendemail.multiedit::
+sendemail.signedoffbycc::
+sendemail.smtppass::
+sendemail.suppresscc::
+sendemail.suppressfrom::
+sendemail.to::
+sendemail.smtpserver::
+sendemail.smtpserverport::
+sendemail.smtpuser::
+sendemail.thread::
+sendemail.validate::
+       See linkgit:git-send-email[1] for description.
+
+sendemail.signedoffcc::
+       Deprecated alias for 'sendemail.signedoffbycc'.
+
 showbranch.default::
        The default set of branches for linkgit:git-show-branch[1].
        See linkgit:git-show-branch[1].
index 1eeb1c76838c1911fc4d57b36a16dece0538809a..b71712473ed13020bca3f133ea4a28c5081b7f9e 100644 (file)
@@ -1,4 +1,7 @@
-The output format from "git-diff-index", "git-diff-tree",
+Raw output format
+-----------------
+
+The raw output format from "git-diff-index", "git-diff-tree",
 "git-diff-files" and "git diff --raw" are very similar.
 
 These commands all compare two sets of things; what is
@@ -16,6 +19,9 @@ git-diff-tree [-r] <tree-ish-1> <tree-ish-2> [<pattern>...]::
 git-diff-files [<pattern>...]::
         compares the index and the files on the filesystem.
 
+The "git-diff-tree" command begins its ouput by printing the hash of
+what is being compared. After that, all the commands print one output
+line per changed file.
 
 An output line is formatted this way:
 
index d313795fdbc420e3395adc42aebe82fabda037d4..ea3b1bc19f753ca80bc133ae614d2c79810a1cb0 100644 (file)
@@ -1,7 +1,7 @@
 -q::
 --quiet::
        Pass --quiet to git-fetch-pack and silence any other internally
-       used programs.
+       used git commands.
 
 -v::
 --verbose::
index ab1943c71243df245f84ede7a69e4c666a8d8834..e67b7e875efb465505a969dfe0d29814c87ac9a6 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 [verse]
 'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
          [--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
-         [--refresh] [--ignore-errors] [--] <filepattern>...
+         [--refresh] [--ignore-errors] [--] [<filepattern>...]
 
 DESCRIPTION
 -----------
index b14de6c407b8bd0bc001c608ca4f26fc619abf3e..2c63a0fbaee0e246538607c8e2f983eb6eafa8e5 100644 (file)
@@ -72,8 +72,16 @@ These objects may be removed by normal git operations (such as 'git-commit')
 which automatically call `git gc --auto`. (See linkgit:git-gc[1].)
 If these objects are removed and were referenced by the cloned repository,
 then the cloned repository will become corrupt.
-
-
++
+Note that running `git repack` without the `-l` option in a repository
+cloned with `-s` will copy objects from the source repository into a pack
+in the cloned repository, removing the disk space savings of `clone -s`.
+It is safe, however, to run `git gc`, which uses the `-l` option by
+default.
++
+If you want to break the dependency of a repository cloned with `-s` on
+its source repository, you can simply run `git repack -a` to copy all
+objects from the source repository into a pack in the cloned repository.
 
 --reference <repository>::
        If the reference repository is on the local machine
index c5261415643d359648900e17f522ba7b96fed44a..4ef03578ebc58f3b678e8805644ae8c0ad4b998b 100644 (file)
@@ -43,8 +43,7 @@ omit diff output for unmerged entries and just show "Unmerged".
 -q::
        Remain silent even on nonexistent files
 
-Output format
--------------
+
 include::diff-format.txt[]
 
 
index 26920d4f63cd213ff17ab28d8dd0dbea94482147..8b9ed2929980ec9928930496375df5e9d72e4b51 100644 (file)
@@ -34,8 +34,6 @@ include::diff-options.txt[]
        'git-diff-index' say that all non-checked-out files are up
        to date.
 
-Output format
--------------
 include::diff-format.txt[]
 
 Operating Modes
index 23b7abd3c6b0e02eb325983eaad66598c42fc8be..f2cef1260b7f74254b96ce65f8aa55267b618c29 100644 (file)
@@ -159,8 +159,7 @@ HEAD commits it finds, which is even more interesting.
 
 in case you care).
 
-Output format
--------------
+
 include::diff-format.txt[]
 
 
index a2f192fb7519117f8e47f3ec4608e3301c200dc3..0ac711230e24bf7238b2e3a215cdc3c4ce0d2087 100644 (file)
@@ -84,8 +84,7 @@ include::diff-options.txt[]
        the diff to the named paths (you can give directory
        names and get diff for all files under them).
 
-Output format
--------------
+
 include::diff-format.txt[]
 
 EXAMPLES
index 0c9eb567cb3e3af89a2e2613d1e074941fa30d13..af2328d401cef30311996cf0376ad17c83c6c516 100644 (file)
@@ -36,6 +36,17 @@ when encountering a signed tag.  With 'strip', the tags will be made
 unsigned, with 'verbatim', they will be silently exported
 and with 'warn', they will be exported, but you will see a warning.
 
+--tag-of-filtered-object=(abort|drop|rewrite)::
+       Specify how to handle tags whose tagged objectis filtered out.
+       Since revisions and files to export can be limited by path,
+       tagged objects may be filtered completely.
++
+When asking to 'abort' (which is the default), this program will die
+when encountering such a tag.  With 'drop' it will omit such tags from
+the output.  With 'rewrite', if the tagged object is a commit, it will
+rewrite the tag to tag an ancestor commit (via parent rewriting; see
+linkgit:git-rev-list[1])
+
 -M::
 -C::
        Perform move and/or copy detection, as described in the
@@ -71,6 +82,12 @@ marks the same across runs.
        allow that.  So fake a tagger to be able to fast-import the
        output.
 
+[git-rev-list-args...]::
+       A list of arguments, acceptable to 'git-rev-parse' and
+       'git-rev-list', that specifies the specific objects and references
+       to export.  For example, `master\~10..master` causes the
+       current master reference to be exported along with all objects
+       added since its 10th ancestor commit.
 
 EXAMPLES
 --------
index ab527b5b316a81eddd8a0eefb501448a3097182f..32ea8564a5d0c5ffebb251353569aeda8c02f651 100644 (file)
@@ -305,6 +305,16 @@ range in addition to the new branch name.  The new branch name will
 point to the top-most revision that a 'git-rev-list' of this range
 will print.
 
+If you need to add 'Acked-by' lines to, say, the last 10 commits (none
+of which is a merge), use this command:
+
+--------------------------------------------------------
+git filter-branch --msg-filter '
+       cat &&
+       echo "Acked-by: Bugs Bunny <bunny@bugzilla.org>"
+' HEAD~10..HEAD
+--------------------------------------------------------
+
 *NOTE* the changes introduced by the commits, and which are not reverted
 by subsequent commits, will still be in the rewritten branch. If you want
 to throw out _changes_ together with the commits, you should use the
index 6f1fc80119600c419d2e3b98bac0c44f9cb09026..687e66759817bc2f349e8a5a89aa2c6731237b23 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git format-patch' [-k] [(-o|--output-directory) <dir> | --stdout]
-                  [--thread[=<style>]]
+                  [--no-thread | --thread[=<style>]]
                   [(--attach|--inline)[=<boundary>] | --no-attach]
                   [-s | --signoff]
                   [-n | --numbered | -N | --no-numbered]
@@ -124,17 +124,25 @@ include::diff-options.txt[]
        second part, with "Content-Disposition: inline".
 
 --thread[=<style>]::
-       Add In-Reply-To and References headers to make the second and
-       subsequent mails appear as replies to the first.  Also generates
-       the Message-Id header to reference.
+--no-thread::
+       Controls addition of In-Reply-To and References headers to
+       make the second and subsequent mails appear as replies to the
+       first.  Also controls generation of the Message-Id header to
+       reference.
 +
 The optional <style> argument can be either `shallow` or `deep`.
 'shallow' threading makes every mail a reply to the head of the
 series, where the head is chosen from the cover letter, the
 `\--in-reply-to`, and the first patch mail, in this order.  'deep'
-threading makes every mail a reply to the previous one.  If not
-specified, defaults to the 'format.thread' configuration, or `shallow`
-if that is not set.
+threading makes every mail a reply to the previous one.
++
+The default is --no-thread, unless the 'format.thread' configuration
+is set.  If --thread is specified without a style, it defaults to the
+style specified by 'format.thread' if any, or else `shallow`.
++
+Beware that the default for 'git send-email' is to thread emails
+itself.  If you want 'git format-patch' to take care of hreading, you
+will want to ensure that threading is disabled for 'git send-email'.
 
 --in-reply-to=Message-Id::
        Make the first mail (or all the mails with --no-thread) appear as a
index c04ae739edd409307d286fe31e6f87e41f977eac..af68d694a0ad8066b05fcc02bae8e57a7c137034 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
-       [-m <msg>] <remote> <remote>...
+       [-m <msg>] <remote>...
 'git merge' <msg> HEAD <remote>...
 
 DESCRIPTION
index 7d4c1a75562de80aa80dfbfa665330b14ec948c6..2e4992970e84a1789cb97d35969976d12e5a30e1 100644 (file)
@@ -11,7 +11,8 @@ SYNOPSIS
 [verse]
 'git pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty]
        [--local] [--incremental] [--window=N] [--depth=N] [--all-progress]
-       [--revs [--unpacked | --all]*] [--stdout | base-name] < object-list
+       [--revs [--unpacked | --all]*] [--stdout | base-name]
+       [--keep-true-parents] < object-list
 
 
 DESCRIPTION
@@ -197,6 +198,10 @@ base-name::
        to force the version for the generated pack index, and to force
        64-bit index entries on objects located above the given offset.
 
+--keep-true-parents::
+       With this option, parents that are hidden by grafts are packed
+       nevertheless.
+
 
 Author
 ------
index 2653388fd8f5fac9292ece83a116accdf0978902..58d2bd5d4a9c27ad6f8246f4768e5ee3764187c8 100644 (file)
@@ -195,6 +195,92 @@ reason::
        refs, no explanation is needed. For a failed ref, the reason for
        failure is described.
 
+Note about fast-forwards
+------------------------
+
+When an update changes a branch (or more in general, a ref) that used to
+point at commit A to point at another commit B, it is called a
+fast-forward update if and only if B is a descendant of A.
+
+In a fast-forward update from A to B, the set of commits that the original
+commit A built on top of is a subset of the commits the new commit B
+builds on top of.  Hence, it does not lose any history.
+
+In contrast, a non-fast-forward update will lose history.  For example,
+suppose you and somebody else started at the same commit X, and you built
+a history leading to commit B while the other person built a history
+leading to commit A.  The history looks like this:
+
+----------------
+
+      B
+     /
+ ---X---A
+
+----------------
+
+Further suppose that the other person already pushed changes leading to A
+back to the original repository you two obtained the original commit X.
+
+The push done by the other person updated the branch that used to point at
+commit X to point at commit A.  It is a fast-forward.
+
+But if you try to push, you will attempt to update the branch (that
+now points at A) with commit B.  This does _not_ fast-forward.  If you did
+so, the changes introduced by commit A will be lost, because everybody
+will now start building on top of B.
+
+The command by default does not allow an update that is not a fast-forward
+to prevent such loss of history.
+
+If you do not want to lose your work (history from X to B) nor the work by
+the other person (history from X to A), you would need to first fetch the
+history from the repository, create a history that contains changes done
+by both parties, and push the result back.
+
+You can perform "git pull", resolve potential conflicts, and "git push"
+the result.  A "git pull" will create a merge commit C between commits A
+and B.
+
+----------------
+
+      B---C
+     /   /
+ ---X---A
+
+----------------
+
+Updating A with the resulting merge commit will fast-forward and your
+push will be accepted.
+
+Alternatively, you can rebase your change between X and B on top of A,
+with "git pull --rebase", and push the result back.  The rebase will
+create a new commit D that builds the change between X and B on top of
+A.
+
+----------------
+
+      B   D
+     /   /
+ ---X---A
+
+----------------
+
+Again, updating A with this commit will fast-forward and your push will be
+accepted.
+
+There is another common situation where you may encounter non-fast-forward
+rejection when you try to push, and it is possible even when you are
+pushing into a repository nobody else pushes into. After you push commit
+A yourself (in the first picture in this section), replace it with "git
+commit --amend" to produce commit B, and you try to push it out, because
+forgot that you have pushed A out already. In such a case, and only if
+you are certain that nobody in the meantime fetched your earlier commit A
+(and started building on top of it), you can run "git push --force" to
+overwrite it. In other words, "git push --force" is a method reserved for
+a case where you do mean to lose history.
+
+
 Examples
 --------
 
index 9e2b4eaa385db66ffe0c547f0452d29e9e3dc484..82a3d296736e515d4f99732e31369c8cdccc2cfd 100644 (file)
@@ -114,14 +114,14 @@ These stale branches have already been removed from the remote repository
 referenced by <name>, but are still locally available in
 "remotes/<name>".
 +
-With `--dry-run` option, report what branches will be pruned, but do no
+With `--dry-run` option, report what branches will be pruned, but do not
 actually prune them.
 
 'update'::
 
 Fetch updates for a named set of remotes in the repository as defined by
 remotes.<group>.  If a named group is not specified on the command line,
-the configuration parameter remotes.default will get used; if
+the configuration parameter remotes.default will be used; if
 remotes.default is not defined, all remotes which do not have the
 configuration parameter remote.<name>.skipDefaultUpdate set to true will
 be updated.  (See linkgit:git-config[1]).
index a53c3cd35b8d6c8be27d90f64013b377d205f201..7dd515b8ccde701ccf5743f80b3b762813ea90c9 100644 (file)
@@ -23,7 +23,7 @@ on the initial manual merge, and applying previously recorded
 hand resolutions to their corresponding automerge results.
 
 [NOTE]
-You need to set the configuration variable rerere.enabled to
+You need to set the configuration variable rerere.enabled in order to
 enable this command.
 
 
index a765cfa4d208ed42a9539c3f26192b2ba4ec05a5..974d9f527f2efb78c435689d7f8bf2bdc807e88d 100644 (file)
@@ -84,7 +84,7 @@ between the two operands.  The following two commands are equivalent:
        $ git rev-list A...B
 -----------------------------------------------------------------------
 
-'git-rev-list' is a very essential git program, since it
+'rev-list' is a very essential git command, since it
 provides the ability to build and traverse commit ancestry graphs. For
 this reason, it has a lot of different options that enables it to be
 used by commands as different as 'git-bisect' and
index fbde2d3be523443c8388f9bb43cc0d5682658f8f..d6b192b7b9d6c7d67703b5e2984a9fed7ffcea3b 100644 (file)
@@ -212,11 +212,22 @@ specified, as well as 'body' if --no-signed-off-cc is specified.
        value; if that is unspecified, default to --no-suppress-from.
 
 --[no-]thread::
-       If this is set, the In-Reply-To header will be set on each email sent.
-       If disabled with "--no-thread", no emails will have the In-Reply-To
-       header set, unless specified with --in-reply-to.
-       Default is the value of the 'sendemail.thread' configuration
-       value; if that is unspecified, default to --thread.
+       If this is set, the In-Reply-To and References headers will be
+       added to each email sent.  Whether each mail refers to the
+       previous email (`deep` threading per 'git format-patch'
+       wording) or to the first email (`shallow` threading) is
+       governed by "--[no-]chain-reply-to".
++
+If disabled with "--no-thread", those headers will not be added
+(unless specified with --in-reply-to).  Default is the value of the
+'sendemail.thread' configuration value; if that is unspecified,
+default to --thread.
++
+It is up to the user to ensure that no In-Reply-To header already
+exists when 'git send-email' is asked to add it (especially note that
+'git format-patch' can be configured to do the threading itself).
+Failure to do so may not produce the expected result in the
+recipient's MUA.
 
 
 Administering
index 683ba1a1ebe080e6e093d27686068823448e459c..7dd73ae14eb38fd5bd291c2251f64768d198ebe5 100644 (file)
@@ -14,8 +14,8 @@ SYNOPSIS
 'git submodule' [--quiet] status [--cached] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
-             [--reference <repository>] [--] [<path>...]
-'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
+             [--reference <repository>] [--merge] [--] [<path>...]
+'git submodule' [--quiet] summary [--cached] [--summary-limit <n>] [commit] [--] [<path>...]
 'git submodule' [--quiet] foreach <command>
 'git submodule' [--quiet] sync [--] [<path>...]
 
index 10af599b44a38981126af62652815b5d184e6774..22a0389f1ed12a79f0b5784c30e0b2be9716c170 100644 (file)
@@ -80,6 +80,17 @@ COMMANDS
        When passed to 'init' or 'clone' this regular expression will
        be preserved as a config key.  See 'fetch' for a description
        of '--ignore-paths'.
+--no-minimize-url;;
+       When tracking multiple directories (using --stdlayout,
+       --branches, or --tags options), git svn will attempt to connect
+       to the root (or highest allowed level) of the Subversion
+       repository.  This default allows better tracking of history if
+       entire projects are moved within a repository, but may cause
+       issues on repositories where read access restrictions are in
+       place.  Passing '--no-minimize-url' will allow git svn to
+       accept URLs as-is without attempting to connect to a higher
+       level directory.  This option is off by default when only
+       one URL/branch is tracked (it would do little good).
 
 'fetch'::
        Fetch unfetched revisions from the Subversion remote we are
@@ -338,6 +349,10 @@ Any other arguments are passed directly to 'git log'
        Shows the Subversion externals.  Use -r/--revision to specify a
        specific revision.
 
+'gc'::
+       Compress $GIT_DIR/svn/<refname>/unhandled.log files in .git/svn
+       and remove $GIT_DIR/svn/<refname>index files in .git/svn.
+
 'reset'::
        Undoes the effects of 'fetch' back to the specified revision.
        This allows you to re-'fetch' an SVN revision.  Normally the
index 210fde03a12cd757769f81754e789a2a5934f02c..63925388073b17c3087d32813979513580adfa2a 100644 (file)
@@ -14,9 +14,9 @@ DESCRIPTION
 Given one argument, reads which branch head the given symbolic
 ref refers to and outputs its path, relative to the `.git/`
 directory.  Typically you would give `HEAD` as the <name>
-argument to see on which branch your working tree is on.
+argument to see which branch your working tree is on.
 
-Give two arguments, create or update a symbolic ref <name> to
+Given two arguments, creates or updates a symbolic ref <name> to
 point at the given branch <ref>.
 
 A symbolic ref is a regular file that stores a string that
index 6fa0310e05f2457ea95a8535460634d0f46cbce8..5832c752e17d8c069e189e4a3a9e84527c318338 100644 (file)
@@ -43,9 +43,15 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.6.3.3/git.html[documentation for release 1.6.3.3]
+* link:v1.6.4/git.html[documentation for release 1.6.4]
 
 * release notes for
+  link:RelNotes-1.6.4.txt[1.6.4].
+
+* link:v1.6.3.4/git.html[documentation for release 1.6.3.4]
+
+* release notes for
+  link:RelNotes-1.6.3.4.txt[1.6.3.4],
   link:RelNotes-1.6.3.3.txt[1.6.3.3],
   link:RelNotes-1.6.3.2.txt[1.6.3.2],
   link:RelNotes-1.6.3.1.txt[1.6.3.1],
@@ -321,7 +327,7 @@ Synching repositories
 
 include::cmds-synchingrepositories.txt[]
 
-The following are helper programs used by the above; end users
+The following are helper commands used by the above; end users
 typically do not use them directly.
 
 include::cmds-synchelpers.txt[]
index aaa073efc80522a649f17d60127aae8cc85b0b3b..1195e83b6e65b5cf7926c973c730ffe19ff92202 100644 (file)
@@ -404,7 +404,7 @@ Performing a three-way merge
 
 The attribute `merge` affects how three versions of a file is
 merged when a file-level merge is necessary during `git merge`,
-and other programs such as `git revert` and `git cherry-pick`.
+and other commands such as `git revert` and `git cherry-pick`.
 
 Set::
 
index 7ba5e589d7e824c526482c9707a5c26ac730cc9e..b3640c4e64494689841e598cf17741ea8620af12 100644 (file)
@@ -12,7 +12,7 @@ git *
 DESCRIPTION
 -----------
 
-This tutorial explains how to use the "core" git programs to set up and
+This tutorial explains how to use the "core" git commands to set up and
 work with a git repository.
 
 If you just need to use git as a revision control system you may prefer
@@ -1328,7 +1328,7 @@ into it later. Obviously, this repository creation needs to be
 done only once.
 
 [NOTE]
-'git-push' uses a pair of programs,
+'git-push' uses a pair of commands,
 'git-send-pack' on your local machine, and 'git-receive-pack'
 on the remote machine. The communication between the two over
 the network internally uses an SSH connection.
index 0b88a51d0b192a3dbc2ec0fe73a32860247377a1..67ebffa568fd684afd08496281a530c658a217d9 100644 (file)
@@ -4131,7 +4131,7 @@ What does this mean?
 
 `git rev-list` is the original version of the revision walker, which
 _always_ printed a list of revisions to stdout.  It is still functional,
-and needs to, since most new Git programs start out as scripts using
+and needs to, since most new Git commands start out as scripts using
 `git rev-list`.
 
 `git rev-parse` is not as important any more; it was only used to filter out
index 39cde784c947fae6a2f294caac1898b9199d769d..d8ae315140a508a333319c38c7e8c0b1ce827a1d 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.6.3.GIT
+DEF_VER=v1.6.4
 
 LF='
 '
index bde27ed478c29a9e5866219eec09a76c828b7ce7..daf4296706c4c9c524b6ec4434cadcf95881ea25 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -728,6 +728,7 @@ ifeq ($(uname_S),SunOS)
        NO_MKDTEMP = YesPlease
        NO_MKSTEMPS = YesPlease
        NO_REGEX = YesPlease
+       NO_EXTERNAL_GREP = YesPlease
        ifeq ($(uname_R),5.7)
                NEEDS_RESOLV = YesPlease
                NO_IPV6 = YesPlease
index 5687d6042ced29e60aa1999dc9d73eb6c38b8e77..1a03d5f356009de12364c320577e24853bec7959 100644 (file)
@@ -191,7 +191,7 @@ struct ref_item {
 
 struct ref_list {
        struct rev_info revs;
-       int index, alloc, maxwidth;
+       int index, alloc, maxwidth, verbose, abbrev;
        struct ref_item *list;
        struct commit_list *with_commit;
        int kinds;
@@ -240,21 +240,24 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
        if (ARRAY_SIZE(ref_kind) <= i)
                return 0;
 
-       commit = lookup_commit_reference_gently(sha1, 1);
-       if (!commit)
-               return error("branch '%s' does not point at a commit", refname);
-
-       /* Filter with with_commit if specified */
-       if (!is_descendant_of(commit, ref_list->with_commit))
-               return 0;
-
        /* Don't add types the caller doesn't want */
        if ((kind & ref_list->kinds) == 0)
                return 0;
 
-       if (merge_filter != NO_FILTER)
-               add_pending_object(&ref_list->revs,
-                                  (struct object *)commit, refname);
+       commit = NULL;
+       if (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) {
+               commit = lookup_commit_reference_gently(sha1, 1);
+               if (!commit)
+                       return error("branch '%s' does not point at a commit", refname);
+
+               /* Filter with with_commit if specified */
+               if (!is_descendant_of(commit, ref_list->with_commit))
+                       return 0;
+
+               if (merge_filter != NO_FILTER)
+                       add_pending_object(&ref_list->revs,
+                                          (struct object *)commit, refname);
+       }
 
        /* Resize buffer */
        if (ref_list->index >= ref_list->alloc) {
@@ -415,18 +418,38 @@ static int calc_maxwidth(struct ref_list *refs)
        return w;
 }
 
+
+static void show_detached(struct ref_list *ref_list)
+{
+       struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);
+
+       if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) {
+               struct ref_item item;
+               item.name = xstrdup("(no branch)");
+               item.len = strlen(item.name);
+               item.kind = REF_LOCAL_BRANCH;
+               item.dest = NULL;
+               item.commit = head_commit;
+               if (item.len > ref_list->maxwidth)
+                       ref_list->maxwidth = item.len;
+               print_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->abbrev, 1, "");
+               free(item.name);
+       }
+}
+
 static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit)
 {
        int i;
        struct ref_list ref_list;
-       struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);
 
        memset(&ref_list, 0, sizeof(ref_list));
        ref_list.kinds = kinds;
+       ref_list.verbose = verbose;
+       ref_list.abbrev = abbrev;
        ref_list.with_commit = with_commit;
        if (merge_filter != NO_FILTER)
                init_revisions(&ref_list.revs, NULL);
-       for_each_ref(append_ref, &ref_list);
+       for_each_rawref(append_ref, &ref_list);
        if (merge_filter != NO_FILTER) {
                struct commit *filter;
                filter = lookup_commit_reference_gently(merge_filter_ref, 0);
@@ -442,19 +465,8 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str
        qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
 
        detached = (detached && (kinds & REF_LOCAL_BRANCH));
-       if (detached && head_commit &&
-           is_descendant_of(head_commit, with_commit)) {
-               struct ref_item item;
-               item.name = xstrdup("(no branch)");
-               item.len = strlen(item.name);
-               item.kind = REF_LOCAL_BRANCH;
-               item.dest = NULL;
-               item.commit = head_commit;
-               if (item.len > ref_list.maxwidth)
-                       ref_list.maxwidth = item.len;
-               print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1, "");
-               free(item.name);
-       }
+       if (detached)
+               show_detached(&ref_list);
 
        for (i = 0; i < ref_list.index; i++) {
                int current = !detached &&
index 9a8a6fc6b1e98162a1548b40bd4281172e18d7b2..c48c18d0c89d1050a531d0521135c2bed9e3b77d 100644 (file)
@@ -23,7 +23,8 @@ static const char *fast_export_usage[] = {
 };
 
 static int progress;
-static enum { VERBATIM, WARN, STRIP, ABORT } signed_tag_mode = ABORT;
+static enum { ABORT, VERBATIM, WARN, STRIP } signed_tag_mode = ABORT;
+static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ABORT;
 static int fake_missing_tagger;
 
 static int parse_opt_signed_tag_mode(const struct option *opt,
@@ -42,6 +43,20 @@ static int parse_opt_signed_tag_mode(const struct option *opt,
        return 0;
 }
 
+static int parse_opt_tag_of_filtered_mode(const struct option *opt,
+                                         const char *arg, int unset)
+{
+       if (unset || !strcmp(arg, "abort"))
+               tag_of_filtered_mode = ABORT;
+       else if (!strcmp(arg, "drop"))
+               tag_of_filtered_mode = DROP;
+       else if (!strcmp(arg, "rewrite"))
+               tag_of_filtered_mode = REWRITE;
+       else
+               return error("Unknown tag-of-filtered mode: %s", arg);
+       return 0;
+}
+
 static struct decoration idnums;
 static uint32_t last_idnum;
 
@@ -289,6 +304,23 @@ static void handle_tag(const char *name, struct tag *tag)
        char *buf;
        const char *tagger, *tagger_end, *message;
        size_t message_size = 0;
+       struct object *tagged;
+       int tagged_mark;
+       struct commit *p;
+
+       /* Trees have no identifer in fast-export output, thus we have no way
+        * to output tags of trees, tags of tags of trees, etc.  Simply omit
+        * such tags.
+        */
+       tagged = tag->tagged;
+       while (tagged->type == OBJ_TAG) {
+               tagged = ((struct tag *)tagged)->tagged;
+       }
+       if (tagged->type == OBJ_TREE) {
+               warning("Omitting tag %s,\nsince tags of trees (or tags of tags of trees, etc.) are not supported.",
+                       sha1_to_hex(tag->object.sha1));
+               return;
+       }
 
        buf = read_sha1_file(tag->object.sha1, &type, &size);
        if (!buf)
@@ -333,10 +365,45 @@ static void handle_tag(const char *name, struct tag *tag)
                        }
        }
 
+       /* handle tag->tagged having been filtered out due to paths specified */
+       tagged = tag->tagged;
+       tagged_mark = get_object_mark(tagged);
+       if (!tagged_mark) {
+               switch(tag_of_filtered_mode) {
+               case ABORT:
+                       die ("Tag %s tags unexported object; use "
+                            "--tag-of-filtered-object=<mode> to handle it.",
+                            sha1_to_hex(tag->object.sha1));
+               case DROP:
+                       /* Ignore this tag altogether */
+                       return;
+               case REWRITE:
+                       if (tagged->type != OBJ_COMMIT) {
+                               die ("Tag %s tags unexported %s!",
+                                    sha1_to_hex(tag->object.sha1),
+                                    typename(tagged->type));
+                       }
+                       p = (struct commit *)tagged;
+                       for (;;) {
+                               if (p->parents && p->parents->next)
+                                       break;
+                               if (p->object.flags & UNINTERESTING)
+                                       break;
+                               if (!(p->object.flags & TREESAME))
+                                       break;
+                               if (!p->parents)
+                                       die ("Can't find replacement commit for tag %s\n",
+                                            sha1_to_hex(tag->object.sha1));
+                               p = p->parents->item;
+                       }
+                       tagged_mark = get_object_mark(&p->object);
+               }
+       }
+
        if (!prefixcmp(name, "refs/tags/"))
                name += 10;
        printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
-              name, get_object_mark(tag->tagged),
+              name, tagged_mark,
               (int)(tagger_end - tagger), tagger,
               tagger == tagger_end ? "" : "\n",
               (int)message_size, (int)message_size, message ? message : "");
@@ -428,21 +495,27 @@ static void export_marks(char *file)
        uint32_t mark;
        struct object_decoration *deco = idnums.hash;
        FILE *f;
+       int e = 0;
 
        f = fopen(file, "w");
        if (!f)
-               error("Unable to open marks file %s for writing", file);
+               error("Unable to open marks file %s for writing.", file);
 
        for (i = 0; i < idnums.size; i++) {
                if (deco->base && deco->base->type == 1) {
                        mark = ptr_to_mark(deco->decoration);
-                       fprintf(f, ":%"PRIu32" %s\n", mark,
-                               sha1_to_hex(deco->base->sha1));
+                       if (fprintf(f, ":%"PRIu32" %s\n", mark,
+                               sha1_to_hex(deco->base->sha1)) < 0) {
+                           e = 1;
+                           break;
+                       }
                }
                deco++;
        }
 
-       if (ferror(f) || fclose(f))
+       e |= ferror(f);
+       e |= fclose(f);
+       if (e)
                error("Unable to write marks file %s.", file);
 }
 
@@ -498,6 +571,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
                OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, "mode",
                             "select handling of signed tags",
                             parse_opt_signed_tag_mode),
+               OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, "mode",
+                            "select handling of tags that tag filtered objects",
+                            parse_opt_tag_of_filtered_mode),
                OPT_STRING(0, "export-marks", &export_filename, "FILE",
                             "Dump marks to this file"),
                OPT_STRING(0, "import-marks", &import_filename, "FILE",
@@ -514,6 +590,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        git_config(git_default_config, NULL);
 
        init_revisions(&revs, prefix);
+       revs.topo_order = 1;
+       revs.show_source = 1;
+       revs.rewrite_parents = 1;
        argc = setup_revisions(argc, argv, &revs, NULL);
        argc = parse_options(argc, argv, prefix, options, fast_export_usage, 0);
        if (argc > 1)
@@ -524,18 +603,13 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 
        get_tags_and_duplicates(&revs.pending, &extra_refs);
 
-       revs.topo_order = 1;
        if (prepare_revision_walk(&revs))
                die("revision walk setup failed");
        revs.diffopt.format_callback = show_filemodify;
        DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
        while ((commit = get_revision(&revs))) {
                if (has_unshown_parent(commit)) {
-                       struct commit_list *parent = commit->parents;
                        add_object_array(&commit->object, NULL, &commits);
-                       for (; parent; parent = parent->next)
-                               if (!parent->item->util)
-                                       parent->item->util = commit->util;
                }
                else {
                        handle_commit(commit, &revs);
index a27c2f6277cd55951cec5d9b5b207df426ed9ff0..ef4bf6bc14aadffcd85999c2eca59e5a0e7e6451 100644 (file)
@@ -2255,6 +2255,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                                die("bad %s", arg);
                        continue;
                }
+               if (!strcmp(arg, "--keep-true-parents")) {
+                       grafts_replace_parents = 0;
+                       continue;
+               }
                usage(pack_usage);
        }
 
index 0a0297f981121924a3ccc8ee52c9b2051f3d410d..50328f4b08e6fc69bb80a9649df2065efb0a9b2c 100644 (file)
@@ -64,36 +64,11 @@ static void setup_push_tracking(void)
        add_refspec(refspec.buf);
 }
 
-static const char *warn_unconfigured_push_msg[] = {
-       "You did not specify any refspecs to push, and the current remote",
-       "has not configured any push refspecs. The default action in this",
-       "case is to push all matching refspecs, that is, all branches",
-       "that exist both locally and remotely will be updated.  This may",
-       "not necessarily be what you want to happen.",
-       "",
-       "You can specify what action you want to take in this case, and",
-       "avoid seeing this message again, by configuring 'push.default' to:",
-       "  'nothing'  : Do not push anything",
-       "  'matching' : Push all matching branches (default)",
-       "  'tracking' : Push the current branch to whatever it is tracking",
-       "  'current'  : Push the current branch"
-};
-
-static void warn_unconfigured_push(void)
-{
-       int i;
-       for (i = 0; i < ARRAY_SIZE(warn_unconfigured_push_msg); i++)
-               warning("%s", warn_unconfigured_push_msg[i]);
-}
-
 static void setup_default_push_refspecs(void)
 {
        git_config(git_default_config, NULL);
        switch (push_default) {
-       case PUSH_DEFAULT_UNSPECIFIED:
-               warn_unconfigured_push();
-               /* fallthrough */
-
+       default:
        case PUSH_DEFAULT_MATCHING:
                add_refspec(":");
                break;
@@ -165,6 +140,7 @@ static int do_push(const char *repo, int flags)
                struct transport *transport =
                        transport_get(remote, url[i]);
                int err;
+               int nonfastforward;
                if (receivepack)
                        transport_set_option(transport,
                                             TRANS_OPT_RECEIVEPACK, receivepack);
@@ -173,13 +149,19 @@ static int do_push(const char *repo, int flags)
 
                if (flags & TRANSPORT_PUSH_VERBOSE)
                        fprintf(stderr, "Pushing to %s\n", url[i]);
-               err = transport_push(transport, refspec_nr, refspec, flags);
+               err = transport_push(transport, refspec_nr, refspec, flags,
+                                    &nonfastforward);
                err |= transport_disconnect(transport);
 
                if (!err)
                        continue;
 
                error("failed to push some refs to '%s'", url[i]);
+               if (nonfastforward) {
+                       printf("To prevent you from losing history, non-fast-forward updates were rejected.\n"
+                              "Merge the remote changes before pushing again.\n"
+                              "See 'non-fast forward' section of 'git push --help' for details.\n");
+               }
                errs++;
        }
        return !!errs;
index ddfdf5a3cbc79003dfbad14af8d1f047e3594aa6..95198c5de41072bfb8adf7f29d9bbb44eec665ac 100644 (file)
@@ -694,7 +694,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
  */
 
 static const char reflog_usage[] =
-"git reflog (expire | ...)";
+"git reflog [ show | expire | delete ]";
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
index 0ee0a9af60b0601fe0e6db98ec582e059f5e9064..a18df04cf94c5a9720f8ccc3346f1dc5077eb692 100644 (file)
@@ -7,10 +7,13 @@
 
 static void show_pack_info(struct packed_git *p)
 {
-       uint32_t nr_objects, i, chain_histogram[MAX_CHAIN+1];
+       uint32_t nr_objects, i;
+       int cnt;
+       unsigned long chain_histogram[MAX_CHAIN+1], baseobjects;
 
        nr_objects = p->num_objects;
        memset(chain_histogram, 0, sizeof(chain_histogram));
+       baseobjects = 0;
 
        for (i = 0; i < nr_objects; i++) {
                const unsigned char *sha1;
@@ -29,9 +32,11 @@ static void show_pack_info(struct packed_git *p)
                                                 &delta_chain_length,
                                                 base_sha1);
                printf("%s ", sha1_to_hex(sha1));
-               if (!delta_chain_length)
+               if (!delta_chain_length) {
                        printf("%-6s %lu %lu %"PRIuMAX"\n",
                               type, size, store_size, (uintmax_t)offset);
+                       baseobjects++;
+               }
                else {
                        printf("%-6s %lu %lu %"PRIuMAX" %u %s\n",
                               type, size, store_size, (uintmax_t)offset,
@@ -43,15 +48,21 @@ static void show_pack_info(struct packed_git *p)
                }
        }
 
-       for (i = 0; i <= MAX_CHAIN; i++) {
-               if (!chain_histogram[i])
+       if (baseobjects)
+               printf("non delta: %lu object%s\n",
+                      baseobjects, baseobjects > 1 ? "s" : "");
+
+       for (cnt = 1; cnt <= MAX_CHAIN; cnt++) {
+               if (!chain_histogram[cnt])
                        continue;
-               printf("chain length = %"PRIu32": %"PRIu32" object%s\n", i,
-                      chain_histogram[i], chain_histogram[i] > 1 ? "s" : "");
+               printf("chain length = %d: %lu object%s\n", cnt,
+                      chain_histogram[cnt],
+                      chain_histogram[cnt] > 1 ? "s" : "");
        }
        if (chain_histogram[0])
-               printf("chain length > %d: %"PRIu32" object%s\n", MAX_CHAIN,
-                      chain_histogram[0], chain_histogram[0] > 1 ? "s" : "");
+               printf("chain length > %d: %lu object%s\n", MAX_CHAIN,
+                      chain_histogram[0],
+                      chain_histogram[0] > 1 ? "s" : "");
 }
 
 static int verify_one_pack(const char *path, int verbose)
diff --git a/cache.h b/cache.h
index f1e5ede02189061a99bb1c8600cbe3f0e3c8e41b..e6c7f3307d09e592aa5bcc63fe6d372aa54a5da3 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -543,7 +543,6 @@ enum rebase_setup_type {
 };
 
 enum push_default_type {
-       PUSH_DEFAULT_UNSPECIFIED = -1,
        PUSH_DEFAULT_NOTHING = 0,
        PUSH_DEFAULT_MATCHING,
        PUSH_DEFAULT_TRACKING,
@@ -561,6 +560,8 @@ enum object_creation_mode {
 
 extern enum object_creation_mode object_creation_mode;
 
+extern int grafts_replace_parents;
+
 #define GIT_REPO_VERSION 0
 extern int repository_format_version;
 extern int check_repository_format(void);
index bbf74fc42e4e72eb3df99272fb75a03bbeaf726a..5b63af1eeb71907f23117bc552fa7a4019f09722 100644 (file)
@@ -80,6 +80,7 @@ struct lline {
 /* Lines surviving in the merge result */
 struct sline {
        struct lline *lost_head, **lost_tail;
+       struct lline *next_lost;
        char *bol;
        int len;
        /* bit 0 up to (N-1) are on if the parent has this line (i.e.
@@ -121,18 +122,12 @@ static void append_lost(struct sline *sline, int n, const char *line, int len)
 
        /* Check to see if we can squash things */
        if (sline->lost_head) {
-               struct lline *last_one = NULL;
-               /* We cannot squash it with earlier one */
-               for (lline = sline->lost_head;
-                    lline;
-                    lline = lline->next)
-                       if (lline->parent_map & this_mask)
-                               last_one = lline;
-               lline = last_one ? last_one->next : sline->lost_head;
+               lline = sline->next_lost;
                while (lline) {
                        if (lline->len == len &&
                            !memcmp(lline->line, line, len)) {
                                lline->parent_map |= this_mask;
+                               sline->next_lost = lline->next;
                                return;
                        }
                        lline = lline->next;
@@ -147,6 +142,7 @@ static void append_lost(struct sline *sline, int n, const char *line, int len)
        lline->line[len] = 0;
        *sline->lost_tail = lline;
        sline->lost_tail = &lline->next;
+       sline->next_lost = NULL;
 }
 
 struct combine_diff_state {
@@ -168,25 +164,28 @@ static void consume_line(void *state_, char *line, unsigned long len)
                                      &state->nb, &state->nn))
                        return;
                state->lno = state->nb;
-               if (!state->nb)
-                       /* @@ -1,2 +0,0 @@ to remove the
-                        * first two lines...
-                        */
-                       state->nb = 1;
-               if (state->nn == 0)
+               if (state->nn == 0) {
                        /* @@ -X,Y +N,0 @@ removed Y lines
                         * that would have come *after* line N
                         * in the result.  Our lost buckets hang
                         * to the line after the removed lines,
+                        *
+                        * Note that this is correct even when N == 0,
+                        * in which case the hunk removes the first
+                        * line in the file.
                         */
                        state->lost_bucket = &state->sline[state->nb];
-               else
+                       if (!state->nb)
+                               state->nb = 1;
+               } else {
                        state->lost_bucket = &state->sline[state->nb-1];
+               }
                if (!state->sline[state->nb-1].p_lno)
                        state->sline[state->nb-1].p_lno =
                                xcalloc(state->num_parent,
                                        sizeof(unsigned long));
                state->sline[state->nb-1].p_lno[state->n] = state->ob;
+               state->lost_bucket->next_lost = state->lost_bucket->lost_head;
                return;
        }
        if (!state->lost_bucket)
index a47fb4da271beaf5595b6bbbe41f94bad08f404d..e2bcbe814936989e7a86018e46ed6ca86f4c1f10 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -262,7 +262,11 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
                    bufptr[47] != '\n')
                        return error("bad parents in commit %s", sha1_to_hex(item->object.sha1));
                bufptr += 48;
-               if (graft)
+               /*
+                * The clone is shallow if nr_parent < 0, and we must
+                * not traverse its real parents even when we unhide them.
+                */
+               if (graft && (graft->nr_parent < 0 || grafts_replace_parents))
                        continue;
                new_parent = lookup_commit(parent);
                if (new_parent)
index 1682273c12ab042d73fa32caf30d18fb13ef85e3..e87edeab0c6b9579ecbd9bc5a9a11c3522d21ccf 100644 (file)
--- a/config.c
+++ b/config.c
@@ -62,7 +62,8 @@ static char *parse_value(void)
                if (comment)
                        continue;
                if (isspace(c) && !quote) {
-                       space = 1;
+                       if (len)
+                               space++;
                        continue;
                }
                if (!quote) {
@@ -71,11 +72,8 @@ static char *parse_value(void)
                                continue;
                        }
                }
-               if (space) {
-                       if (len)
-                               value[len++] = ' ';
-                       space = 0;
-               }
+               for (; space; space--)
+                       value[len++] = ' ';
                if (c == '\\') {
                        c = get_next_char();
                        switch (c) {
@@ -1174,7 +1172,9 @@ int git_config_set_multivar(const char *key, const char *value,
 static int section_name_match (const char *buf, const char *name)
 {
        int i = 0, j = 0, dot = 0;
-       for (; buf[i] && buf[i] != ']'; i++) {
+       if (buf[i] != '[')
+               return 0;
+       for (i = 1; buf[i] && buf[i] != ']'; i++) {
                if (!dot && isspace(buf[i])) {
                        dot = 1;
                        if (name[j++] != '.')
@@ -1195,7 +1195,17 @@ static int section_name_match (const char *buf, const char *name)
                if (buf[i] != name[j++])
                        break;
        }
-       return (buf[i] == ']' && name[j] == 0);
+       if (buf[i] == ']' && name[j] == 0) {
+               /*
+                * We match, now just find the right length offset by
+                * gobbling up any whitespace after it, as well
+                */
+               i++;
+               for (; buf[i] && isspace(buf[i]); i++)
+                       ; /* do nothing */
+               return i;
+       }
+       return 0;
 }
 
 /* if new_name == NULL, the section is removed instead */
@@ -1225,11 +1235,13 @@ int git_config_rename_section(const char *old_name, const char *new_name)
        while (fgets(buf, sizeof(buf), config_file)) {
                int i;
                int length;
+               char *output = buf;
                for (i = 0; buf[i] && isspace(buf[i]); i++)
                        ; /* do nothing */
                if (buf[i] == '[') {
                        /* it's a section */
-                       if (section_name_match (&buf[i+1], old_name)) {
+                       int offset = section_name_match(&buf[i], old_name);
+                       if (offset > 0) {
                                ret++;
                                if (new_name == NULL) {
                                        remove = 1;
@@ -1240,14 +1252,29 @@ int git_config_rename_section(const char *old_name, const char *new_name)
                                        ret = write_error(lock->filename);
                                        goto out;
                                }
-                               continue;
+                               /*
+                                * We wrote out the new section, with
+                                * a newline, now skip the old
+                                * section's length
+                                */
+                               output += offset + i;
+                               if (strlen(output) > 0) {
+                                       /*
+                                        * More content means there's
+                                        * a declaration to put on the
+                                        * next line; indent with a
+                                        * tab
+                                        */
+                                       output -= 1;
+                                       output[0] = '\t';
+                               }
                        }
                        remove = 0;
                }
                if (remove)
                        continue;
-               length = strlen(buf);
-               if (write_in_full(out_fd, buf, length) != length) {
+               length = strlen(output);
+               if (write_in_full(out_fd, output, length) != length) {
                        ret = write_error(lock->filename);
                        goto out;
                }
index dd6045131880111bb09306cb3e48330a0e5acdac..67b12f73a1bb795207082973701ece8009167f1c 100644 (file)
@@ -34,6 +34,7 @@ NO_LIBGEN_H=@NO_LIBGEN_H@
 NEEDS_LIBICONV=@NEEDS_LIBICONV@
 NEEDS_SOCKET=@NEEDS_SOCKET@
 NEEDS_RESOLV=@NEEDS_RESOLV@
+NEEDS_LIBGEN=@NEEDS_LIBGEN@
 NO_SYS_SELECT_H=@NO_SYS_SELECT_H@
 NO_D_INO_IN_DIRENT=@NO_D_INO_IN_DIRENT@
 NO_D_TYPE_IN_DIRENT=@NO_D_TYPE_IN_DIRENT@
index 74d0af52a5d4f2443a49e16127bab652daa80697..3f1922d0bf66abdbcad03dfd9981ca5293a4b860 100644 (file)
@@ -342,9 +342,8 @@ GIT_STASH_FLAGS($OPENSSLDIR)
 AC_CHECK_LIB([crypto], [SHA1_Init],
 [NEEDS_SSL_WITH_CRYPTO=],
 [AC_CHECK_LIB([ssl], [SHA1_Init],
- [NEEDS_SSL_WITH_CRYPTO=YesPlease
-  NEEDS_SSL_WITH_CRYPTO=],
- [NO_OPENSSL=YesPlease])])
+ [NEEDS_SSL_WITH_CRYPTO=YesPlease],
+ [NEEDS_SSL_WITH_CRYPTO= NO_OPENSSL=YesPlease])])
 
 GIT_UNSTASH_FLAGS($OPENSSLDIR)
 
@@ -479,13 +478,13 @@ test -n "$NEEDS_SOCKET" && LIBS="$LIBS -lsocket"
 # Define NEEDS_RESOLV if linking with -lnsl and/or -lsocket is not enough.
 # Notably on Solaris hstrerror resides in libresolv and on Solaris 7
 # inet_ntop and inet_pton additionally reside there.
-AC_CHECK_LIB([resolv], [hstrerror],
+AC_CHECK_LIB([c], [hstrerror],
 [NEEDS_RESOLV=],
 [NEEDS_RESOLV=YesPlease])
 AC_SUBST(NEEDS_RESOLV)
 test -n "$NEEDS_RESOLV" && LIBS="$LIBS -lresolv"
 
-AC_CHECK_LIB([gen], [basename],
+AC_CHECK_LIB([c], [basename],
 [NEEDS_LIBGEN=],
 [NEEDS_LIBGEN=YesPlease])
 AC_SUBST(NEEDS_LIBGEN)
index 887731e830b8e41d647d1961061d9c75cd441621..745b5fb78be02086d7d94aaaeaa40930150430f9 100755 (executable)
 #       GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
 #       then a '$' will be shown next to the branch name.
 #
+#       If you would like to see if there're untracked files, then you can
+#       set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
+#       untracked files, then a '%' will be shown next to the branch name.
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -132,6 +136,7 @@ __git_ps1 ()
                local w
                local i
                local s
+               local u
                local c
 
                if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
@@ -156,12 +161,18 @@ __git_ps1 ()
                        if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
                                git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
                        fi
+
+                       if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ]; then
+                          if [ -n "$(git ls-files --others --exclude-standard)" ]; then
+                             u="%"
+                          fi
+                       fi
                fi
 
                if [ -n "${1-}" ]; then
-                       printf "$1" "$c${b##refs/heads/}$w$i$s$r"
+                       printf "$1" "$c${b##refs/heads/}$w$i$s$u$r"
                else
-                       printf " (%s)" "$c${b##refs/heads/}$w$i$s$r"
+                       printf " (%s)" "$c${b##refs/heads/}$w$i$s$u$r"
                fi
        fi
 }
index 7b03204ed18500756ba55818f0808b52db68d048..2a6839d81ee970cb799859c7a833f8f8cb780864 100755 (executable)
@@ -20,7 +20,7 @@
 """
 
 import os, os.path, sys
-import tempfile, popen2, pickle, getopt
+import tempfile, pickle, getopt
 import re
 
 # Maps hg version -> git version
index 801a005ef1b23ef13cfa9ece676c550fe35dedc0..8f5eaa7dd89cbedd5a89e11f0ea24b29701b33c9 100644 (file)
@@ -42,11 +42,12 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
 enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
-enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
+enum push_default_type push_default = PUSH_DEFAULT_MATCHING;
 #ifndef OBJECT_CREATION_MODE
 #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
 #endif
 enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
+int grafts_replace_parents = 1;
 
 /* Parallel index stat data preload? */
 int core_preload_index = 0;
index 913f41a42cfb1ef07416069c3c36a734011914e7..9f941e42b16d927f738b4911b41344dd2f3ed0da 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define bitsizeof(x)  (CHAR_BIT * sizeof(x))
 
 #ifdef __GNUC__
 #define TYPEOF(x) (__typeof__(x))
 #define TYPEOF(x)
 #endif
 
-#define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
+#define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (bitsizeof(x) - (bits))))
 #define HAS_MULTI_BITS(i)  ((i) & ((i) - 1))  /* checks if an integer has more than 1 bit set */
 
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+
 /* Approximation of the length of the decimal representation of this type. */
 #define decimal_length(x)      ((int)(sizeof(x) * 2.56 + 0.5) + 1)
 
index 37e044db40bb89470bb64a4108c86d5173e03b5a..a480d6fc70a4ca738c8ead14052afc3c1f5e8b02 100755 (executable)
@@ -97,12 +97,12 @@ set_ident () {
        echo "case \"\$GIT_${uid}_NAME\" in \"\") GIT_${uid}_NAME=\"\${GIT_${uid}_EMAIL%%@*}\" && export GIT_${uid}_NAME;; esac"
 }
 
-USAGE="[--env-filter <command>] [--tree-filter <command>] \
-[--index-filter <command>] [--parent-filter <command>] \
-[--msg-filter <command>] [--commit-filter <command>] \
-[--tag-name-filter <command>] [--subdirectory-filter <directory>] \
-[--original <namespace>] [-d <directory>] [-f | --force] \
-[<rev-list options>...]"
+USAGE="[--env-filter <command>] [--tree-filter <command>]
+            [--index-filter <command>] [--parent-filter <command>]
+            [--msg-filter <command>] [--commit-filter <command>]
+            [--tag-name-filter <command>] [--subdirectory-filter <directory>]
+            [--original <namespace>] [-d <directory>] [-f | --force]
+            [<rev-list options>...]"
 
 OPTIONS_SPEC=
 . git-sh-setup
index 5f4419b69b58769e8fee7a60109520a095a831c5..5f5cac75eaa6fbf2ca68cfa01de2b21afa352cd0 100755 (executable)
@@ -256,7 +256,7 @@ apache2_conf () {
        mkdir -p "$GIT_DIR/gitweb/logs"
        bind=
        test x"$local" = xtrue && bind='127.0.0.1:'
-       echo 'text/css css' > $fqgitdir/mime.types
+       echo 'text/css css' > "$fqgitdir/mime.types"
        cat > "$conf" <<EOF
 ServerName "git-instaweb"
 ServerRoot "$fqgitdir/gitweb"
@@ -272,13 +272,13 @@ EOF
                fi
        done
        cat >> "$conf" <<EOF
-TypesConfig $fqgitdir/mime.types
+TypesConfig "$fqgitdir/mime.types"
 DirectoryIndex gitweb.cgi
 EOF
 
        # check to see if Dennis Stosberg's mod_perl compatibility patch
        # (<20060621130708.Gcbc6e5c@leonov.stosberg.net>) has been applied
-       if test -f "$module_path/mod_perl.so" && grep '^our $gitbin' \
+       if test -f "$module_path/mod_perl.so" && grep 'MOD_PERL' \
                                "$GIT_DIR/gitweb/gitweb.cgi" >/dev/null
        then
                # favor mod_perl if available
index f96d887d23653019e3387eced2779d50b3f09fa2..23ded48322bf795b06aa40e4684bc710c8232549 100755 (executable)
@@ -703,7 +703,7 @@ first and then run 'git rebase --continue' again."
                                        preserve=t
                                        for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
                                        do
-                                               if test -f "$REWRITTEN"/$p -a \( $p != $UPSTREAM -o $sha1 = $first_after_upstream \)
+                                               if test -f "$REWRITTEN"/$p -a \( $p != $ONTO -o $sha1 = $first_after_upstream \)
                                                then
                                                        preserve=f
                                                fi
index 1bf239499c7bdb04622ea6fa239bd7c0ace42065..1eb3bca352f38ec3807383cc5fff7f7e62731b2b 100755 (executable)
@@ -81,7 +81,7 @@ case ",$all_into_one," in
 esac
 
 args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
-names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
+names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
        exit 1
 if [ -z "$names" ]; then
        say Nothing new to pack.
index 5917773240dfb2e8b5f078afee22a3d9bf607ce3..fd95beadab6aa01fc3fb26c7d72ba182201f8502 100755 (executable)
@@ -28,13 +28,13 @@ headrev=`git rev-parse --verify "$head"^0` || exit
 merge_base=`git merge-base $baserev $headrev` ||
 die "fatal: No commits in common between $base and $head"
 
-url=$(get_remote_url "$url")
 branch=$(git ls-remote "$url" \
        | sed -n -e "/^$headrev refs.heads./{
                s/^.*   refs.heads.//
                p
                q
        }")
+url=$(get_remote_url "$url")
 if [ -z "$branch" ]; then
        echo "warn: No branch of $url is at:" >&2
        git log --max-count=1 --pretty='tformat:warn:   %h: %s' $headrev >&2
index 8ce6f1fe57579201c09cf960caed98d330ab2bbb..0700d80afcf99dfafbd34731bf3c359b7d921ff3 100755 (executable)
@@ -450,7 +450,6 @@ ($)
        try {
                $repo->command('rev-parse', '--verify', '--quiet', $f);
                if (defined($format_patch)) {
-                       print "foo\n";
                        return $format_patch;
                }
                die(<<EOF);
@@ -654,13 +653,17 @@ sub ask {
 }
 
 sub expand_aliases {
-       my @cur = @_;
-       my @last;
-       do {
-               @last = @cur;
-               @cur = map { $aliases{$_} ? @{$aliases{$_}} : $_ } @last;
-       } while (join(',',@cur) ne join(',',@last));
-       return @cur;
+       return map { expand_one_alias($_) } @_;
+}
+
+my %EXPANDED_ALIASES;
+sub expand_one_alias {
+       my $alias = shift;
+       if ($EXPANDED_ALIASES{$alias}) {
+               die "fatal: alias '$alias' expands to itself\n";
+       }
+       local $EXPANDED_ALIASES{$alias} = 1;
+       return $aliases{$alias} ? expand_aliases(@{$aliases{$alias}}) : $alias;
 }
 
 @to = expand_aliases(@to);
index 531c7c31aca87db77e54c46ffb89899652a79fcd..03e589f764ba0570559fdb23a9a11cc2a0f24044 100755 (executable)
@@ -203,7 +203,7 @@ apply_stash () {
                git diff-tree --binary $s^2^..$s^2 | git apply --cached
                test $? -ne 0 &&
                        die 'Conflicts in index. Try without --index.'
-               unstashed_index_tree=$(git-write-tree) ||
+               unstashed_index_tree=$(git write-tree) ||
                        die 'Could not save index tree'
                git reset
        fi
@@ -219,7 +219,7 @@ apply_stash () {
        then
                export GIT_MERGE_VERBOSITY=0
        fi
-       if git-merge-recursive $b_tree -- $c_tree $w_tree
+       if git merge-recursive $b_tree -- $c_tree $w_tree
        then
                # No conflict
                if test -n "$unstashed_index_tree"
@@ -297,7 +297,7 @@ apply_to_branch () {
        fi
        stash=$2
 
-       git-checkout -b $branch $stash^ &&
+       git checkout -b $branch $stash^ &&
        apply_stash --index $stash &&
        drop_stash $stash
 }
index cfade63459a77ffa0e79d85fbe9e3aae174789e6..d0758107249f3743795d0961d36906452ac7d00a 100755 (executable)
@@ -19,6 +19,7 @@
 $Git::SVN::default_repo_id = 'svn';
 $Git::SVN::default_ref_id = $ENV{GIT_SVN_ID} || 'git-svn';
 $Git::SVN::Ra::_log_window_size = 100;
+$Git::SVN::_minimize_url = 'unset';
 
 $Git::SVN::Log::TZ = $ENV{TZ};
 $ENV{TZ} = 'UTC';
@@ -31,6 +32,7 @@
 if ($SVN::Core::VERSION lt '1.1.0') {
        fatal "Need SVN::Core 1.1.0 or better (got $SVN::Core::VERSION)";
 }
+my $can_compress = eval { require Compress::Zlib; 1};
 push @Git::SVN::Ra::ISA, 'SVN::Ra';
 push @SVN::Git::Editor::ISA, 'SVN::Delta::Editor';
 push @SVN::Git::Fetcher::ISA, 'SVN::Delta::Editor';
@@ -40,6 +42,7 @@
 use File::Basename qw/dirname basename/;
 use File::Path qw/mkpath/;
 use File::Spec;
+use File::Find;
 use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
 use IPC::Open3;
 use Git;
@@ -98,7 +101,7 @@ BEGIN
                   'trunk|T=s' => \$_trunk, 'tags|t=s@' => \@_tags,
                   'branches|b=s@' => \@_branches, 'prefix=s' => \$_prefix,
                   'stdlayout|s' => \$_stdlayout,
-                  'minimize-url|m' => \$Git::SVN::_minimize_url,
+                  'minimize-url|m!' => \$Git::SVN::_minimize_url,
                  'no-metadata' => sub { $icv{noMetadata} = 1 },
                  'use-svm-props' => sub { $icv{useSvmProps} = 1 },
                  'use-svnsync-props' => sub { $icv{useSvnsyncProps} = 1 },
@@ -217,6 +220,10 @@ BEGIN
                     "Undo fetches back to the specified SVN revision",
                     { 'revision|r=s' => \$_revision,
                       'parent|p' => \$_fetch_parent } ],
+       'gc' => [ \&cmd_gc,
+                 "Compress unhandled.log files in .git/svn and remove " .
+                 "index files in .git/svn",
+               {} ],
 );
 
 my $cmd;
@@ -393,6 +400,10 @@ sub cmd_init {
        init_subdir(@_);
        do_git_init_db();
 
+       if ($Git::SVN::_minimize_url eq 'unset') {
+               $Git::SVN::_minimize_url = 0;
+       }
+
        Git::SVN->init($url);
 }
 
@@ -655,9 +666,22 @@ sub cmd_branch {
                        }
                }
                unless (defined $glob) {
-                       die "Unknown ",
-                           $_tag ? "tag" : "branch",
-                           " destination $_branch_dest\n";
+                       my $dest_re = qr/\b\Q$_branch_dest\E\b/;
+                       foreach my $g (@{$allglobs}) {
+                               $g->{path}->{left} =~ /$dest_re/ or next;
+                               if (defined $glob) {
+                                       die "Ambiguous destination: ",
+                                           $_branch_dest, "\nmatches both '",
+                                           $glob->{path}->{left}, "' and '",
+                                           $g->{path}->{left}, "'\n";
+                               }
+                               $glob = $g;
+                       }
+                       unless (defined $glob) {
+                               die "Unknown ",
+                                   $_tag ? "tag" : "branch",
+                                   " destination $_branch_dest\n";
+                       }
                }
        }
        my ($lft, $rgt) = @{ $glob->{path} }{qw/left right/};
@@ -1107,6 +1131,14 @@ sub cmd_reset {
        print "r$r = $c ($gs->{ref_id})\n";
 }
 
+sub cmd_gc {
+       if (!$can_compress) {
+               warn "Compress::Zlib could not be found; unhandled.log " .
+                    "files will not be compressed.\n";
+       }
+       find({ wanted => \&gc_directory, no_chdir => 1}, "$ENV{GIT_DIR}/svn");
+}
+
 ########################### utility functions #########################
 
 sub rebase_cmd {
@@ -1527,6 +1559,25 @@ sub md5sum {
        return $md5->hexdigest();
 }
 
+sub gc_directory {
+       if ($can_compress && -f $_ && basename($_) eq "unhandled.log") {
+               my $out_filename = $_ . ".gz";
+               open my $in_fh, "<", $_ or die "Unable to open $_: $!\n";
+               binmode $in_fh;
+               my $gz = Compress::Zlib::gzopen($out_filename, "ab") or
+                               die "Unable to open $out_filename: $!\n";
+
+               my $res;
+               while ($res = sysread($in_fh, my $str, 1024)) {
+                       $gz->gzwrite($str) or
+                               die "Unable to write: ".$gz->gzerror()."!\n";
+               }
+               unlink $_ or die "unlink $File::Find::name: $!\n";
+       } elsif (-f $_ && basename($_) eq "index") {
+               unlink $_ or die "unlink $_: $!\n";
+       }
+}
+
 package Git::SVN;
 use strict;
 use warnings;
@@ -1647,6 +1698,7 @@ sub fetch_all {
        my $ra = Git::SVN::Ra->new($url);
        my $uuid = $ra->get_uuid;
        my $head = $ra->get_latest_revnum;
+       $ra->get_log("", $head, 0, 1, 0, 1, sub { $head = $_[1] });
        my $base = defined $fetch ? $head : 0;
 
        # read the max revs for wildcard expansion (branches/*, tags/*)
@@ -3953,7 +4005,7 @@ sub repo_path {
 sub url_path {
        my ($self, $path) = @_;
        if ($self->{url} =~ m#^https?://#) {
-               $path =~ s/([^~a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
+               $path =~ s!([^~a-zA-Z0-9_./-])!uc sprintf("%%%02x",ord($1))!eg;
        }
        $self->{url} . '/' . $self->repo_path($path);
 }
@@ -4525,10 +4577,12 @@ sub gs_do_switch {
 
        my $full_url = $self->{url};
        my $old_url = $full_url;
-       $full_url .= '/' . escape_uri_only($path) if length $path;
+       $full_url .= '/' . $path if length $path;
        my ($ra, $reparented);
 
-       if ($old_url =~ m#^svn(\+ssh)?://#) {
+       if ($old_url =~ m#^svn(\+ssh)?://# ||
+           ($full_url =~ m#^https?://# &&
+            escape_url($full_url) ne $full_url)) {
                $_[0] = undef;
                $self = undef;
                $RA = undef;
@@ -4777,7 +4831,11 @@ sub minimize_url {
        my $c = '';
        do {
                $url .= "/$c" if length $c;
-               eval { (ref $self)->new($url)->get_latest_revnum };
+               eval {
+                       my $ra = (ref $self)->new($url);
+                       my $latest = $ra->get_latest_revnum;
+                       $ra->get_log("", $latest, 0, 1, 0, 1, sub {});
+               };
        } while ($@ && ($c = shift @components));
        $url;
 }
index 9056d1e090b314cfa617ccd8aa03047b3aea23b4..66c6a9391d3494ae8928e88501d8fa0d36dffa42 100644 (file)
@@ -165,6 +165,12 @@ not include variables usually directly set during build):
    Full URL and absolute URL of gitweb script;
    in earlier versions of gitweb you might have need to set those
    variables, now there should be no need to do it.
+ * $base_url
+   Base URL for relative URLs in pages generated by gitweb,
+   (e.g. $logo, $favicon, @stylesheets if they are relative URLs),
+   needed and used only for URLs with nonempty PATH_INFO via
+   <base href="$base_url>.  Usually gitweb sets its value correctly,
+   and there is no need to set this variable, e.g. to $my_uri or "/".
  * $home_link
    Target of the home link on top of all pages (the first part of view
    "breadcrumbs").  By default set to absolute URI of a page ($my_uri).
diff --git a/graph.c b/graph.c
index f8d7a5c0f6d17538a72b75e8de9dd092829a0262..e466770208d73d8e1f5bc7f6b12728b6f2b7c6bb 100644 (file)
--- a/graph.c
+++ b/graph.c
@@ -893,7 +893,7 @@ static struct column *find_new_column_by_commit(struct git_graph *graph,
                if (graph->new_columns[i].commit == commit)
                        return &graph->new_columns[i];
        }
-       return 0;
+       return NULL;
 }
 
 static void graph_output_post_merge_line(struct git_graph *graph, struct strbuf *sb)
diff --git a/help.c b/help.c
index fd87bb5aeec82beec600be46248b19b13bb33804..294337e71c0c8f1c3e150dd0b566c04db96c013d 100644 (file)
--- a/help.c
+++ b/help.c
@@ -100,7 +100,7 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest)
 
        if (space < max_cols)
                cols = max_cols / space;
-       rows = (cmds->cnt + cols - 1) / cols;
+       rows = DIV_ROUND_UP(cmds->cnt, cols);
 
        for (i = 0; i < rows; i++) {
                printf("  ");
@@ -302,7 +302,7 @@ const char *help_unknown_cmd(const char *cmd)
        struct cmdnames main_cmds, other_cmds;
 
        memset(&main_cmds, 0, sizeof(main_cmds));
-       memset(&other_cmds, 0, sizeof(main_cmds));
+       memset(&other_cmds, 0, sizeof(other_cmds));
        memset(&aliases, 0, sizeof(aliases));
 
        git_config(git_unknown_cmd_config, NULL);
@@ -334,7 +334,7 @@ const char *help_unknown_cmd(const char *cmd)
                const char *assumed = main_cmds.names[0]->name;
                main_cmds.names[0] = NULL;
                clean_cmdnames(&main_cmds);
-               fprintf(stderr, "WARNING: You called a Git program named '%s', "
+               fprintf(stderr, "WARNING: You called a Git command named '%s', "
                        "which does not exist.\n"
                        "Continuing under the assumption that you meant '%s'\n",
                        cmd, assumed);
index 1de53c8934c03b46604e94cbf4237ad5ffc57f83..77a0465be6f6a79814aa3c009612736770b342a1 100644 (file)
@@ -149,8 +149,7 @@ void discard_revindex(void)
        if (pack_revindex_hashsz) {
                int i;
                for (i = 0; i < pack_revindex_hashsz; i++)
-                       if (pack_revindex[i].revindex)
-                               free(pack_revindex[i].revindex);
+                       free(pack_revindex[i].revindex);
                free(pack_revindex);
                pack_revindex_hashsz = 0;
        }
index 14d52811832d8f2a3f6c1e1e5502c51ce73da82e..92899333c2d8edbed71fdd3a43e19f25a10e5b03 100644 (file)
@@ -76,7 +76,7 @@ static void preload_index(struct index_state *index, const char **pathspec)
        if (threads > MAX_PARALLEL)
                threads = MAX_PARALLEL;
        offset = 0;
-       work = (index->cache_nr + threads - 1) / threads;
+       work = DIV_ROUND_UP(index->cache_nr, threads);
        for (i = 0; i < threads; i++) {
                struct thread_data *p = data+i;
                p->index = index;
diff --git a/refs.c b/refs.c
index dffe395a97a12f2489dc5bbec1f822e3b8f08de5..e49eaa3089c39028e3c0af90422672db63fff198 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -531,9 +531,10 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
 {
        if (strncmp(base, entry->name, trim))
                return 0;
+       /* Is this a "negative ref" that represents a deleted ref? */
+       if (is_null_sha1(entry->sha1))
+               return 0;
        if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
-               if (is_null_sha1(entry->sha1))
-                       return 0;
                if (!has_sha1_file(entry->sha1)) {
                        error("%s does not point to a valid object!", entry->name);
                        return 0;
@@ -1525,8 +1526,10 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs,
                if (fstat(fileno(logfp), &statbuf) ||
                    statbuf.st_size < ofs ||
                    fseek(logfp, -ofs, SEEK_END) ||
-                   fgets(buf, sizeof(buf), logfp))
+                   fgets(buf, sizeof(buf), logfp)) {
+                       fclose(logfp);
                        return -1;
+               }
        }
 
        while (fgets(buf, sizeof(buf), logfp)) {
index 4576ff77f3ceec7231b14261f7386abb2289cd5c..1d996a199036c115d46c1d630d53edf29b3b78e7 100644 (file)
@@ -1170,7 +1170,7 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
        size = c & 15;
        shift = 4;
        while (c & 0x80) {
-               if (len <= used || sizeof(long) * 8 <= shift) {
+               if (len <= used || bitsizeof(long) <= shift) {
                        error("bad object header");
                        return 0;
                }
index 904bcd96a54a1cc33386a56a16d07dce34cbb90b..44bb62d270739a232e87c90c05ce89fcc86bc15b 100644 (file)
@@ -777,8 +777,6 @@ int interpret_branch_name(const char *name, struct strbuf *buf)
        for_each_recent_reflog_ent("HEAD", grab_nth_branch_switch, 40960, &cb);
        if (cb.cnt < nth) {
                cb.cnt = 0;
-               for (i = 0; i < nth; i++)
-                       strbuf_release(&cb.buf[i]);
                for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
        }
        if (cb.cnt < nth)
index 43ea283242c4afc25e53d4a8c894140793649717..83b7294010cd59d5438b6020868c699c01105595 100755 (executable)
@@ -459,6 +459,28 @@ EOF
 
 test_expect_success "rename succeeded" "test_cmp expect .git/config"
 
+cat >> .git/config << EOF
+[branch "vier"] z = 1
+EOF
+
+test_expect_success "rename a section with a var on the same line" \
+       'git config --rename-section branch.vier branch.zwei'
+
+cat > expect << EOF
+# Hallo
+       #Bello
+[branch "zwei"]
+       x = 1
+[branch "zwei"]
+       y = 1
+[branch "drei"]
+weird
+[branch "zwei"]
+       z = 1
+EOF
+
+test_expect_success "rename succeeded" "test_cmp expect .git/config"
+
 cat >> .git/config << EOF
   [branch "zwei"] a = 1 [branch "vier"]
 EOF
@@ -733,6 +755,11 @@ echo >>result
 
 test_expect_success '--null --get-regexp' 'cmp result expect'
 
+test_expect_success 'inner whitespace kept verbatim' '
+       git config section.val "foo       bar" &&
+       test "z$(git config section.val)" = "zfoo         bar"
+'
+
 test_expect_success SYMLINKS 'symlinked configuration' '
 
        ln -s notyet myconfig &&
diff --git a/t/t3414-rebase-preserve-onto.sh b/t/t3414-rebase-preserve-onto.sh
new file mode 100755 (executable)
index 0000000..80019ee
--- /dev/null
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Greg Price
+#
+
+test_description='git rebase -p should respect --onto
+
+In a rebase with --onto, we should rewrite all the commits that
+aren'"'"'t on top of $ONTO, even if they are on top of $UPSTREAM.
+'
+. ./test-lib.sh
+
+. ../lib-rebase.sh
+
+# Set up branches like this:
+# A1---B1---E1---F1---G1
+#  \    \             /
+#   \    \--C1---D1--/
+#    H1
+
+test_expect_success 'setup' '
+       test_commit A1 &&
+       test_commit B1 &&
+       test_commit C1 &&
+       test_commit D1 &&
+       git reset --hard B1 &&
+       test_commit E1 &&
+       test_commit F1 &&
+       test_merge G1 D1 &&
+       git reset --hard A1 &&
+       test_commit H1
+'
+
+# Now rebase merge G1 from both branches' base B1, both should move:
+# A1---B1---E1---F1---G1
+#  \    \             /
+#   \    \--C1---D1--/
+#    \
+#     H1---E2---F2---G2
+#      \             /
+#       \--C2---D2--/
+
+test_expect_success 'rebase from B1 onto H1' '
+       git checkout G1 &&
+       git rebase -p --onto H1 B1 &&
+       test "$(git rev-parse HEAD^1^1^1)" = "$(git rev-parse H1)" &&
+       test "$(git rev-parse HEAD^2^1^1)" = "$(git rev-parse H1)"
+'
+
+# On the other hand if rebase from E1 which is within one branch,
+# then the other branch stays:
+# A1---B1---E1---F1---G1
+#  \    \             /
+#   \    \--C1---D1--/
+#    \             \
+#     H1-----F3-----G3
+
+test_expect_success 'rebase from E1 onto H1' '
+       git checkout G1 &&
+       git rebase -p --onto H1 E1 &&
+       test "$(git rev-parse HEAD^1^1)" = "$(git rev-parse H1)" &&
+       test "$(git rev-parse HEAD^2)" = "$(git rev-parse D1)"
+'
+
+# And the same if we rebase from a commit in the second-parent branch.
+# A1---B1---E1---F1----G1
+#  \    \          \   /
+#   \    \--C1---D1-\-/
+#    \               \
+#     H1------D3------G4
+
+test_expect_success 'rebase from C1 onto H1' '
+       git checkout G1 &&
+       git rev-list --first-parent --pretty=oneline C1..G1 &&
+       git rebase -p --onto H1 C1 &&
+       test "$(git rev-parse HEAD^2^1)" = "$(git rev-parse H1)" &&
+       test "$(git rev-parse HEAD^1)" = "$(git rev-parse F1)"
+'
+
+test_done
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
new file mode 100755 (executable)
index 0000000..2cf7e01
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+test_description='combined diff'
+
+. ./test-lib.sh
+
+setup_helper () {
+       one=$1 branch=$2 side=$3 &&
+
+       git branch $side $branch &&
+       for l in $one two three fyra
+       do
+               echo $l
+       done >file &&
+       git add file &&
+       test_tick &&
+       git commit -m $branch &&
+       git checkout $side &&
+       for l in $one two three quatro
+       do
+               echo $l
+       done >file &&
+       git add file &&
+       test_tick &&
+       git commit -m $side &&
+       test_must_fail git merge $branch &&
+       for l in $one three four
+       do
+               echo $l
+       done >file &&
+       git add file &&
+       test_tick &&
+       git commit -m "merge $branch into $side"
+}
+
+verify_helper () {
+       it=$1 &&
+
+       # Ignore lines that were removed only from the other parent
+       sed -e '
+               1,/^@@@/d
+               /^ -/d
+               s/^\(.\)./\1/
+       ' "$it" >"$it.actual.1" &&
+       sed -e '
+               1,/^@@@/d
+               /^- /d
+               s/^.\(.\)/\1/
+       ' "$it" >"$it.actual.2" &&
+
+       git diff "$it^" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.1" &&
+       test_cmp "$it.expect.1" "$it.actual.1" &&
+
+       git diff "$it^2" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.2" &&
+       test_cmp "$it.expect.2" "$it.actual.2"
+}
+
+test_expect_success setup '
+       >file &&
+       git add file &&
+       test_tick &&
+       git commit -m initial &&
+
+       git branch withone &&
+       git branch sansone &&
+
+       git checkout withone &&
+       setup_helper one withone sidewithone &&
+
+       git checkout sansone &&
+       setup_helper "" sansone sidesansone
+'
+
+test_expect_success 'check combined output (1)' '
+       git show sidewithone -- >sidewithone &&
+       verify_helper sidewithone
+'
+
+test_expect_failure 'check combined output (2)' '
+       git show sidesansone -- >sidesansone &&
+       verify_helper sidesansone
+'
+
+test_done
index f83322e513b96bb90e71ce39340515c6be0db186..fac2093d7f20d502f41f895d2ccdfccd5e639e2b 100755 (executable)
@@ -148,4 +148,26 @@ do
        done
 done
 
+create_patch () {
+       sed -e "s/_/ /" <<-\EOF
+               diff --git a/target b/target
+               index e69de29..8bd6648 100644
+               --- a/target
+               +++ b/target
+               @@ -0,0 +1,3 @@
+               +An empty line follows
+               +
+               +A line with trailing whitespace and no newline_
+               \ No newline at end of file
+       EOF
+}
+
+test_expect_success 'trailing whitespace & no newline at the end of file' '
+       >target &&
+       create_patch >patch-file &&
+       git apply --whitespace=fix patch-file &&
+       grep "newline$" target &&
+       grep "^$" target
+'
+
 test_done
index aad3894ad4c542d4ab894c2d57a035a89eb88258..48e0088b4780e133a450aea01092d9238e7122e9 100755 (executable)
@@ -149,6 +149,26 @@ test_expect_success 'git log --follow' '
 
 '
 
+cat > expect << EOF
+804a787 sixth
+394ef78 fifth
+5d31159 fourth
+EOF
+test_expect_success 'git log --no-walk <commits> sorts by commit time' '
+       git log --no-walk --oneline 5d31159 804a787 394ef78 > actual &&
+       test_cmp expect actual
+'
+
+cat > expect << EOF
+5d31159 fourth
+804a787 sixth
+394ef78 fifth
+EOF
+test_expect_success 'git show <commits> leaves list of commits as given' '
+       git show --oneline -s 5d31159 804a787 394ef78 > actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'setup case sensitivity tests' '
        echo case >one &&
        test_tick &&
index bee3424fed770aacac6dbcdf4ba58bfd7bf5c2da..d13c806624bcc8a404be97d61500e8e1d4614c6b 100755 (executable)
@@ -9,6 +9,11 @@ test_description='Per branch config variables affects "git fetch".
 
 D=`pwd`
 
+test_bundle_object_count () {
+       git verify-pack -v "$1" >verify.out &&
+       test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l)
+}
+
 test_expect_success setup '
        echo >file original &&
        git add file &&
@@ -146,6 +151,7 @@ test_expect_success 'unbundle 1' '
        test_must_fail git fetch "$D/bundle1" master:master
 '
 
+
 test_expect_success 'bundle 1 has only 3 files ' '
        cd "$D" &&
        (
@@ -156,8 +162,7 @@ test_expect_success 'bundle 1 has only 3 files ' '
                cat
        ) <bundle1 >bundle.pack &&
        git index-pack bundle.pack &&
-       verify=$(git verify-pack -v bundle.pack) &&
-       test 4 = $(echo "$verify" | wc -l)
+       test_bundle_object_count bundle.pack 3
 '
 
 test_expect_success 'unbundle 2' '
@@ -180,7 +185,7 @@ test_expect_success 'bundle does not prerequisite objects' '
                cat
        ) <bundle3 >bundle.pack &&
        git index-pack bundle.pack &&
-       test 4 = $(git verify-pack -v bundle.pack | wc -l)
+       test_bundle_object_count bundle.pack 3
 '
 
 test_expect_success 'bundle should be able to create a full history' '
index 87c9b0e121db6c8ab7074e6c4968cd06d37851fe..f4aa0547501a19fe570304e830504ff984f5a9a9 100755 (executable)
@@ -149,5 +149,17 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar
        test_must_fail git show $csha1
 '
 
+test_expect_success 'objects made unreachable by grafts only are kept' '
+       test_tick &&
+       git commit --allow-empty -m "commit 4" &&
+       H0=$(git rev-parse HEAD) &&
+       H1=$(git rev-parse HEAD^) &&
+       H2=$(git rev-parse HEAD^^) &&
+       echo "$H0 $H2" > .git/info/grafts &&
+       git reflog expire --expire=now --expire-unreachable=now --all &&
+       git repack -a -d &&
+       git cat-file -t $H1
+       '
+
 test_done
 
index 9cca14d080e63d25f5d71179deaced8b226bba07..cb390559f947fe3cd89a99b9bd473d60c7083307 100755 (executable)
@@ -4,7 +4,7 @@ test_description='git blame encoding conversion'
 . ./test-lib.sh
 
 . "$TEST_DIRECTORY"/t8005/utf8.txt
-. "$TEST_DIRECTORY"/t8005/iso8859-5.txt
+. "$TEST_DIRECTORY"/t8005/euc-japan.txt
 . "$TEST_DIRECTORY"/t8005/sjis.txt
 
 test_expect_success 'setup the repository' '
@@ -13,10 +13,10 @@ test_expect_success 'setup the repository' '
        git add file &&
        git commit --author "$UTF8_NAME <utf8@localhost>" -m "$UTF8_MSG" &&
 
-       echo "ISO-8859-5 LINE" >> file &&
+       echo "EUC-JAPAN LINE" >> file &&
        git add file &&
-       git config i18n.commitencoding ISO8859-5 &&
-       git commit --author "$ISO8859_5_NAME <iso8859-5@localhost>" -m "$ISO8859_5_MSG" &&
+       git config i18n.commitencoding eucJP &&
+       git commit --author "$EUC_JAPAN_NAME <euc-japan@localhost>" -m "$EUC_JAPAN_MSG" &&
 
        echo "SJIS LINE" >> file &&
        git add file &&
@@ -41,17 +41,17 @@ test_expect_success \
 '
 
 cat >expected <<EOF
-author $ISO8859_5_NAME
-summary $ISO8859_5_MSG
-author $ISO8859_5_NAME
-summary $ISO8859_5_MSG
-author $ISO8859_5_NAME
-summary $ISO8859_5_MSG
+author $EUC_JAPAN_NAME
+summary $EUC_JAPAN_MSG
+author $EUC_JAPAN_NAME
+summary $EUC_JAPAN_MSG
+author $EUC_JAPAN_NAME
+summary $EUC_JAPAN_MSG
 EOF
 
 test_expect_success \
        'blame respects i18n.logoutputencoding' '
-       git config i18n.logoutputencoding ISO8859-5 &&
+       git config i18n.logoutputencoding eucJP &&
        git blame --incremental file | \
                egrep "^(author|summary) " > actual &&
        test_cmp actual expected
@@ -76,8 +76,8 @@ test_expect_success \
 cat >expected <<EOF
 author $SJIS_NAME
 summary $SJIS_MSG
-author $ISO8859_5_NAME
-summary $ISO8859_5_MSG
+author $EUC_JAPAN_NAME
+summary $EUC_JAPAN_MSG
 author $UTF8_NAME
 summary $UTF8_MSG
 EOF
diff --git a/t/t8005/euc-japan.txt b/t/t8005/euc-japan.txt
new file mode 100644 (file)
index 0000000..288f040
--- /dev/null
@@ -0,0 +1,2 @@
+EUC_JAPAN_NAME="»³ÅÄ ÂÀϺ"
+EUC_JAPAN_MSG="¥Ö¥ì¡¼¥à¤Î¥Æ¥¹¥È¤Ç¤¹¡£"
index 2ccfbad207c6e96b1f4f528031d9e4938d364b92..bbdefeaced4b54f98e5d9a85ddd8e0d7346fe7e3 100644 (file)
@@ -1,2 +1,2 @@
-SJIS_NAME="\84I\84r\84p\84\84P\84u\84\84\84\82\84\80\84r\84y\84\89 \84R\84y\84t\84\80\84\82\84\80\84r"
-SJIS_MSG="\84S\84u\84\83\84\84\84\80\84r\84\80\84\84\83\84\80\84\80\84q\84\8b\84u\84~\84y\84u"
+SJIS_NAME="\8eR\93\91¾\98Y"
+SJIS_MSG="\83u\83\8c\81[\83\80\82Ì\83e\83X\83g\82Å\82·\81B"
index f46cfc56d80797740c3ec15e166add052f905fcb..4d00dbea7659ee27fda283e7e45cfb2d5f6ea4d1 100644 (file)
@@ -1,2 +1,2 @@
-UTF8_NAME="Иван Петрович Сидоров"
-UTF8_MSG="Тестовое сообщение"
+UTF8_NAME="山田 太郎"
+UTF8_MSG="ブレームのテストです。"
diff --git a/t/t9138-git-svn-multiple-branches.sh b/t/t9138-git-svn-multiple-branches.sh
deleted file mode 100755 (executable)
index 3cd0671..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2009 Marc Branchaud
-#
-
-test_description='git svn multiple branch and tag paths in the svn repo'
-. ./lib-git-svn.sh
-
-test_expect_success 'setup svnrepo' '
-       mkdir   project \
-               project/trunk \
-               project/b_one \
-               project/b_two \
-               project/tags_A \
-               project/tags_B &&
-       echo 1 > project/trunk/a.file &&
-       svn_cmd import -m "$test_description" project "$svnrepo/project" &&
-       rm -rf project &&
-       svn_cmd cp -m "Branch 1" "$svnrepo/project/trunk" \
-                                "$svnrepo/project/b_one/first" &&
-       svn_cmd cp -m "Tag 1" "$svnrepo/project/trunk" \
-                             "$svnrepo/project/tags_A/1.0" &&
-       svn_cmd co "$svnrepo/project" svn_project &&
-       ( cd svn_project &&
-               echo 2 > trunk/a.file &&
-               svn_cmd ci -m "Change 1" trunk/a.file &&
-               svn_cmd cp -m "Branch 2" "$svnrepo/project/trunk" \
-                                        "$svnrepo/project/b_one/second" &&
-               svn_cmd cp -m "Tag 2" "$svnrepo/project/trunk" \
-                                     "$svnrepo/project/tags_A/2.0" &&
-               echo 3 > trunk/a.file &&
-               svn_cmd ci -m "Change 2" trunk/a.file &&
-               svn_cmd cp -m "Branch 3" "$svnrepo/project/trunk" \
-                                        "$svnrepo/project/b_two/1" &&
-               svn_cmd cp -m "Tag 3" "$svnrepo/project/trunk" \
-                                     "$svnrepo/project/tags_A/3.0" &&
-               echo 4 > trunk/a.file &&
-               svn_cmd ci -m "Change 3" trunk/a.file &&
-               svn_cmd cp -m "Branch 4" "$svnrepo/project/trunk" \
-                                        "$svnrepo/project/b_two/2" &&
-               svn_cmd cp -m "Tag 4" "$svnrepo/project/trunk" \
-                                     "$svnrepo/project/tags_A/4.0" &&
-               svn_cmd up &&
-               echo 5 > b_one/first/a.file &&
-               svn_cmd ci -m "Change 4" b_one/first/a.file &&
-               svn_cmd cp -m "Tag 5" "$svnrepo/project/b_one/first" \
-                                     "$svnrepo/project/tags_B/v5" &&
-               echo 6 > b_one/second/a.file &&
-               svn_cmd ci -m "Change 5" b_one/second/a.file &&
-               svn_cmd cp -m "Tag 6" "$svnrepo/project/b_one/second" \
-                                     "$svnrepo/project/tags_B/v6" &&
-               echo 7 > b_two/1/a.file &&
-               svn_cmd ci -m "Change 6" b_two/1/a.file &&
-               svn_cmd cp -m "Tag 7" "$svnrepo/project/b_two/1" \
-                                     "$svnrepo/project/tags_B/v7" &&
-               echo 8 > b_two/2/a.file &&
-               svn_cmd ci -m "Change 7" b_two/2/a.file &&
-               svn_cmd cp -m "Tag 8" "$svnrepo/project/b_two/2" \
-                                     "$svnrepo/project/tags_B/v8"
-       )
-'
-
-test_expect_success 'clone multiple branch and tag paths' '
-       git svn clone -T trunk \
-                     -b b_one/* --branches b_two/* \
-                     -t tags_A/* --tags tags_B \
-                     "$svnrepo/project" git_project &&
-       ( cd git_project &&
-               git rev-parse refs/remotes/first &&
-               git rev-parse refs/remotes/second &&
-               git rev-parse refs/remotes/1 &&
-               git rev-parse refs/remotes/2 &&
-               git rev-parse refs/remotes/tags/1.0 &&
-               git rev-parse refs/remotes/tags/2.0 &&
-               git rev-parse refs/remotes/tags/3.0 &&
-               git rev-parse refs/remotes/tags/4.0 &&
-               git rev-parse refs/remotes/tags/v5 &&
-               git rev-parse refs/remotes/tags/v6 &&
-               git rev-parse refs/remotes/tags/v7 &&
-               git rev-parse refs/remotes/tags/v8
-       )
-'
-
-test_expect_success 'Multiple branch or tag paths require -d' '
-       ( cd git_project &&
-               test_must_fail git svn branch -m "No new branch" Nope &&
-               test_must_fail git svn tag -m "No new tag" Tagless &&
-               test_must_fail git rev-parse refs/remotes/Nope &&
-               test_must_fail git rev-parse refs/remotes/tags/Tagless
-       ) &&
-       ( cd svn_project &&
-               svn_cmd up &&
-               test_must_fail test -d b_one/Nope &&
-               test_must_fail test -d b_two/Nope &&
-               test_must_fail test -d tags_A/Tagless &&
-               test_must_fail test -d tags_B/Tagless
-       )
-'
-
-test_expect_success 'create new branches and tags' '
-       ( cd git_project &&
-               git svn branch -m "New branch 1" -d b_one New1 ) &&
-       ( cd svn_project &&
-               svn_cmd up && test -e b_one/New1/a.file ) &&
-
-       ( cd git_project &&
-               git svn branch -m "New branch 2" -d b_two New2 ) &&
-       ( cd svn_project &&
-               svn_cmd up && test -e b_two/New2/a.file ) &&
-
-       ( cd git_project &&
-               git svn branch -t -m "New tag 1" -d tags_A Tag1 ) &&
-       ( cd svn_project &&
-               svn_cmd up && test -e tags_A/Tag1/a.file ) &&
-
-       ( cd git_project &&
-               git svn tag -m "New tag 2" -d tags_B Tag2 ) &&
-       ( cd svn_project &&
-               svn_cmd up && test -e tags_B/Tag2/a.file )
-'
-
-test_done
diff --git a/t/t9139-git-svn-reset.sh b/t/t9139-git-svn-reset.sh
deleted file mode 100755 (executable)
index 0735526..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2009 Ben Jackson
-#
-
-test_description='git svn reset'
-. ./lib-git-svn.sh
-
-test_expect_success 'setup test repository' '
-       svn_cmd co "$svnrepo" s &&
-       (
-               cd s &&
-               mkdir vis &&
-               echo always visible > vis/vis.txt &&
-               svn_cmd add vis &&
-               svn_cmd commit -m "create visible files" &&
-               mkdir hid &&
-               echo initially hidden > hid/hid.txt &&
-               svn_cmd add hid &&
-               svn_cmd commit -m "create initially hidden files" &&
-               svn_cmd up &&
-               echo mod >> vis/vis.txt &&
-               svn_cmd commit -m "modify vis" &&
-               svn_cmd up
-       )
-'
-
-test_expect_success 'clone SVN repository with hidden directory' '
-       git svn init "$svnrepo" g &&
-       ( cd g && git svn fetch --ignore-paths="^hid" )
-'
-
-test_expect_success 'modify hidden file in SVN repo' '
-       ( cd s &&
-         echo mod hidden >> hid/hid.txt &&
-         svn_cmd commit -m "modify hid" &&
-         svn_cmd up
-       )
-'
-
-test_expect_success 'fetch fails on modified hidden file' '
-       ( cd g &&
-         git svn find-rev refs/remotes/git-svn > ../expect &&
-         ! git svn fetch 2> ../errors &&
-         git svn find-rev refs/remotes/git-svn > ../expect2 ) &&
-       fgrep "not found in commit" errors &&
-       test_cmp expect expect2
-'
-
-test_expect_success 'reset unwinds back to r1' '
-       ( cd g &&
-         git svn reset -r1 &&
-         git svn find-rev refs/remotes/git-svn > ../expect2 ) &&
-       echo 1 >expect &&
-       test_cmp expect expect2
-'
-
-test_expect_success 'refetch succeeds not ignoring any files' '
-       ( cd g &&
-         git svn fetch &&
-         git svn rebase &&
-         fgrep "mod hidden" hid/hid.txt
-       )
-'
-
-test_done
diff --git a/t/t9140-git-svn-reset.sh b/t/t9140-git-svn-reset.sh
new file mode 100755 (executable)
index 0000000..0735526
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Ben Jackson
+#
+
+test_description='git svn reset'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup test repository' '
+       svn_cmd co "$svnrepo" s &&
+       (
+               cd s &&
+               mkdir vis &&
+               echo always visible > vis/vis.txt &&
+               svn_cmd add vis &&
+               svn_cmd commit -m "create visible files" &&
+               mkdir hid &&
+               echo initially hidden > hid/hid.txt &&
+               svn_cmd add hid &&
+               svn_cmd commit -m "create initially hidden files" &&
+               svn_cmd up &&
+               echo mod >> vis/vis.txt &&
+               svn_cmd commit -m "modify vis" &&
+               svn_cmd up
+       )
+'
+
+test_expect_success 'clone SVN repository with hidden directory' '
+       git svn init "$svnrepo" g &&
+       ( cd g && git svn fetch --ignore-paths="^hid" )
+'
+
+test_expect_success 'modify hidden file in SVN repo' '
+       ( cd s &&
+         echo mod hidden >> hid/hid.txt &&
+         svn_cmd commit -m "modify hid" &&
+         svn_cmd up
+       )
+'
+
+test_expect_success 'fetch fails on modified hidden file' '
+       ( cd g &&
+         git svn find-rev refs/remotes/git-svn > ../expect &&
+         ! git svn fetch 2> ../errors &&
+         git svn find-rev refs/remotes/git-svn > ../expect2 ) &&
+       fgrep "not found in commit" errors &&
+       test_cmp expect expect2
+'
+
+test_expect_success 'reset unwinds back to r1' '
+       ( cd g &&
+         git svn reset -r1 &&
+         git svn find-rev refs/remotes/git-svn > ../expect2 ) &&
+       echo 1 >expect &&
+       test_cmp expect expect2
+'
+
+test_expect_success 'refetch succeeds not ignoring any files' '
+       ( cd g &&
+         git svn fetch &&
+         git svn rebase &&
+         fgrep "mod hidden" hid/hid.txt
+       )
+'
+
+test_done
diff --git a/t/t9141-git-svn-multiple-branches.sh b/t/t9141-git-svn-multiple-branches.sh
new file mode 100755 (executable)
index 0000000..3cd0671
--- /dev/null
@@ -0,0 +1,122 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Marc Branchaud
+#
+
+test_description='git svn multiple branch and tag paths in the svn repo'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup svnrepo' '
+       mkdir   project \
+               project/trunk \
+               project/b_one \
+               project/b_two \
+               project/tags_A \
+               project/tags_B &&
+       echo 1 > project/trunk/a.file &&
+       svn_cmd import -m "$test_description" project "$svnrepo/project" &&
+       rm -rf project &&
+       svn_cmd cp -m "Branch 1" "$svnrepo/project/trunk" \
+                                "$svnrepo/project/b_one/first" &&
+       svn_cmd cp -m "Tag 1" "$svnrepo/project/trunk" \
+                             "$svnrepo/project/tags_A/1.0" &&
+       svn_cmd co "$svnrepo/project" svn_project &&
+       ( cd svn_project &&
+               echo 2 > trunk/a.file &&
+               svn_cmd ci -m "Change 1" trunk/a.file &&
+               svn_cmd cp -m "Branch 2" "$svnrepo/project/trunk" \
+                                        "$svnrepo/project/b_one/second" &&
+               svn_cmd cp -m "Tag 2" "$svnrepo/project/trunk" \
+                                     "$svnrepo/project/tags_A/2.0" &&
+               echo 3 > trunk/a.file &&
+               svn_cmd ci -m "Change 2" trunk/a.file &&
+               svn_cmd cp -m "Branch 3" "$svnrepo/project/trunk" \
+                                        "$svnrepo/project/b_two/1" &&
+               svn_cmd cp -m "Tag 3" "$svnrepo/project/trunk" \
+                                     "$svnrepo/project/tags_A/3.0" &&
+               echo 4 > trunk/a.file &&
+               svn_cmd ci -m "Change 3" trunk/a.file &&
+               svn_cmd cp -m "Branch 4" "$svnrepo/project/trunk" \
+                                        "$svnrepo/project/b_two/2" &&
+               svn_cmd cp -m "Tag 4" "$svnrepo/project/trunk" \
+                                     "$svnrepo/project/tags_A/4.0" &&
+               svn_cmd up &&
+               echo 5 > b_one/first/a.file &&
+               svn_cmd ci -m "Change 4" b_one/first/a.file &&
+               svn_cmd cp -m "Tag 5" "$svnrepo/project/b_one/first" \
+                                     "$svnrepo/project/tags_B/v5" &&
+               echo 6 > b_one/second/a.file &&
+               svn_cmd ci -m "Change 5" b_one/second/a.file &&
+               svn_cmd cp -m "Tag 6" "$svnrepo/project/b_one/second" \
+                                     "$svnrepo/project/tags_B/v6" &&
+               echo 7 > b_two/1/a.file &&
+               svn_cmd ci -m "Change 6" b_two/1/a.file &&
+               svn_cmd cp -m "Tag 7" "$svnrepo/project/b_two/1" \
+                                     "$svnrepo/project/tags_B/v7" &&
+               echo 8 > b_two/2/a.file &&
+               svn_cmd ci -m "Change 7" b_two/2/a.file &&
+               svn_cmd cp -m "Tag 8" "$svnrepo/project/b_two/2" \
+                                     "$svnrepo/project/tags_B/v8"
+       )
+'
+
+test_expect_success 'clone multiple branch and tag paths' '
+       git svn clone -T trunk \
+                     -b b_one/* --branches b_two/* \
+                     -t tags_A/* --tags tags_B \
+                     "$svnrepo/project" git_project &&
+       ( cd git_project &&
+               git rev-parse refs/remotes/first &&
+               git rev-parse refs/remotes/second &&
+               git rev-parse refs/remotes/1 &&
+               git rev-parse refs/remotes/2 &&
+               git rev-parse refs/remotes/tags/1.0 &&
+               git rev-parse refs/remotes/tags/2.0 &&
+               git rev-parse refs/remotes/tags/3.0 &&
+               git rev-parse refs/remotes/tags/4.0 &&
+               git rev-parse refs/remotes/tags/v5 &&
+               git rev-parse refs/remotes/tags/v6 &&
+               git rev-parse refs/remotes/tags/v7 &&
+               git rev-parse refs/remotes/tags/v8
+       )
+'
+
+test_expect_success 'Multiple branch or tag paths require -d' '
+       ( cd git_project &&
+               test_must_fail git svn branch -m "No new branch" Nope &&
+               test_must_fail git svn tag -m "No new tag" Tagless &&
+               test_must_fail git rev-parse refs/remotes/Nope &&
+               test_must_fail git rev-parse refs/remotes/tags/Tagless
+       ) &&
+       ( cd svn_project &&
+               svn_cmd up &&
+               test_must_fail test -d b_one/Nope &&
+               test_must_fail test -d b_two/Nope &&
+               test_must_fail test -d tags_A/Tagless &&
+               test_must_fail test -d tags_B/Tagless
+       )
+'
+
+test_expect_success 'create new branches and tags' '
+       ( cd git_project &&
+               git svn branch -m "New branch 1" -d b_one New1 ) &&
+       ( cd svn_project &&
+               svn_cmd up && test -e b_one/New1/a.file ) &&
+
+       ( cd git_project &&
+               git svn branch -m "New branch 2" -d b_two New2 ) &&
+       ( cd svn_project &&
+               svn_cmd up && test -e b_two/New2/a.file ) &&
+
+       ( cd git_project &&
+               git svn branch -t -m "New tag 1" -d tags_A Tag1 ) &&
+       ( cd svn_project &&
+               svn_cmd up && test -e tags_A/Tag1/a.file ) &&
+
+       ( cd git_project &&
+               git svn tag -m "New tag 2" -d tags_B Tag2 ) &&
+       ( cd svn_project &&
+               svn_cmd up && test -e tags_B/Tag2/a.file )
+'
+
+test_done
diff --git a/t/t9142-git-svn-shallow-clone.sh b/t/t9142-git-svn-shallow-clone.sh
new file mode 100755 (executable)
index 0000000..1236acc
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong
+#
+
+test_description='git svn shallow clone'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup test repository' '
+       svn_cmd mkdir -m "create standard layout" \
+         "$svnrepo"/trunk "$svnrepo"/branches "$svnrepo"/tags &&
+       svn_cmd cp -m "branch off trunk" \
+         "$svnrepo"/trunk "$svnrepo"/branches/a &&
+       svn_cmd co "$svnrepo"/branches/a &&
+       (
+               cd a &&
+               > foo &&
+               svn_cmd add foo &&
+               svn_cmd commit -m "add foo"
+       )
+'
+
+start_httpd
+
+test_expect_success 'clone trunk with "-r HEAD"' '
+       git svn clone -r HEAD "$svnrepo/trunk" g &&
+       ( cd g && git rev-parse --symbolic --verify HEAD )
+'
+
+stop_httpd
+
+test_done
diff --git a/t/t9143-git-svn-gc.sh b/t/t9143-git-svn-gc.sh
new file mode 100755 (executable)
index 0000000..f2ba2d1
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Robert Allan Zeh
+
+test_description='git svn gc basic tests'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'setup directories and test repo' '
+       mkdir import &&
+       mkdir tmp &&
+       echo "Sample text for Subversion repository." > import/test.txt &&
+       svn_cmd import -m "import for git svn" import "$svnrepo" > /dev/null
+       '
+
+test_expect_success 'checkout working copy from svn' \
+       'svn_cmd co "$svnrepo" test_wc'
+
+test_expect_success 'set some properties to create an unhandled.log file' '
+       (
+               cd test_wc &&
+               svn_cmd propset foo bar test.txt &&
+               svn_cmd commit -m "property set"
+       )'
+
+test_expect_success 'Setup repo' 'git svn init "$svnrepo"'
+
+test_expect_success 'Fetch repo' 'git svn fetch'
+
+test_expect_success 'make backup copy of unhandled.log' '
+        cp .git/svn/git-svn/unhandled.log tmp
+       '
+
+test_expect_success 'create leftover index' '> .git/svn/git-svn/index'
+
+test_expect_success 'git svn gc runs' 'git svn gc'
+
+test_expect_success 'git svn index removed' '! test -f .git/svn/git-svn/index'
+
+if perl -MCompress::Zlib -e 0 2>/dev/null
+then
+       test_expect_success 'git svn gc produces a valid gzip file' '
+                gunzip .git/svn/git-svn/unhandled.log.gz
+               '
+else
+       say "Perl Compress::Zlib unavailable, skipping gunzip test"
+fi
+
+test_expect_success 'git svn gc does not change unhandled.log files' '
+        test_cmp .git/svn/git-svn/unhandled.log tmp/unhandled.log
+       '
+
+test_done
index ef1f8d22f67187089ff88811457d8e26cf354047..fc3795dc98803bd98e2ebd6f38a249c331038d54 100755 (executable)
@@ -288,6 +288,27 @@ test_expect_success 'check files before directories' '
 
 '
 
+test_expect_success 're-commit a removed filename which remains in CVS attic' '
+
+    (cd "$CVSWORK" &&
+     echo >attic_gremlin &&
+     cvs -Q add attic_gremlin &&
+     cvs -Q ci -m "added attic_gremlin" &&
+     rm attic_gremlin &&
+     cvs -Q rm attic_gremlin &&
+     cvs -Q ci -m "removed attic_gremlin") &&
+
+    echo > attic_gremlin &&
+    git add attic_gremlin &&
+    git commit -m "Added attic_gremlin" &&
+       git cvsexportcommit -w "$CVSWORK" -c HEAD &&
+    (cd "$CVSWORK"; cvs -Q update -d) &&
+    test -f "$CVSWORK/attic_gremlin"
+'
+
+# the state of the CVS sandbox may be indeterminate for ' space'
+# after this test on some platforms / with some versions of CVS
+# consider adding new tests above this point
 test_expect_success 'commit a file with leading spaces in the name' '
 
        echo space > " space" &&
@@ -295,7 +316,7 @@ test_expect_success 'commit a file with leading spaces in the name' '
        git commit -m "Add a file with a leading space" &&
        id=$(git rev-parse HEAD) &&
        git cvsexportcommit -w "$CVSWORK" -c $id &&
-       check_entries "$CVSWORK" " space/1.1/|DS/1.1/|release-notes/1.2/" &&
+       check_entries "$CVSWORK" " space/1.1/|DS/1.1/|attic_gremlin/1.3/|release-notes/1.2/" &&
        test_cmp "$CVSWORK/ space" " space"
 
 '
@@ -317,22 +338,4 @@ test_expect_success 'use the same checkout for Git and CVS' '
 
 '
 
-test_expect_success 're-commit a removed filename which remains in CVS attic' '
-
-    (cd "$CVSWORK" &&
-     echo >attic_gremlin &&
-     cvs -Q add attic_gremlin &&
-     cvs -Q ci -m "added attic_gremlin" &&
-     rm attic_gremlin &&
-     cvs -Q rm attic_gremlin &&
-     cvs -Q ci -m "removed attic_gremlin") &&
-
-    echo > attic_gremlin &&
-    git add attic_gremlin &&
-    git commit -m "Added attic_gremlin" &&
-       git cvsexportcommit -w "$CVSWORK" -c HEAD &&
-    (cd "$CVSWORK"; cvs -Q update -d) &&
-    test -f "$CVSWORK/attic_gremlin"
-'
-
 test_done
index 8c8a9e63c26c594a837d266bff56f5f85cb376c8..356964e53a1acba1558881865fd99acdee48a17f 100755 (executable)
@@ -262,6 +262,94 @@ test_expect_success 'cope with tagger-less tags' '
 
 '
 
+test_expect_success 'setup for limiting exports by PATH' '
+       mkdir limit-by-paths &&
+       cd limit-by-paths &&
+       git init &&
+       echo hi > there &&
+       git add there &&
+       git commit -m "First file" &&
+       echo foo > bar &&
+       git add bar &&
+       git commit -m "Second file" &&
+       git tag -a -m msg mytag &&
+       echo morefoo >> bar &&
+       git add bar &&
+       git commit -m "Change to second file" &&
+       cd ..
+'
+
+cat > limit-by-paths/expected << EOF
+blob
+mark :1
+data 3
+hi
+
+reset refs/tags/mytag
+commit refs/tags/mytag
+mark :2
+author A U Thor <author@example.com> 1112912713 -0700
+committer C O Mitter <committer@example.com> 1112912713 -0700
+data 11
+First file
+M 100644 :1 there
+
+EOF
+
+test_expect_success 'dropping tag of filtered out object' '
+       cd limit-by-paths &&
+       git fast-export --tag-of-filtered-object=drop mytag -- there > output &&
+       test_cmp output expected &&
+       cd ..
+'
+
+cat >> limit-by-paths/expected << EOF
+tag mytag
+from :2
+tagger C O Mitter <committer@example.com> 1112912713 -0700
+data 4
+msg
+
+EOF
+
+test_expect_success 'rewriting tag of filtered out object' '
+       cd limit-by-paths &&
+       git fast-export --tag-of-filtered-object=rewrite mytag -- there > output &&
+       test_cmp output expected &&
+       cd ..
+'
+
+cat > limit-by-paths/expected << EOF
+blob
+mark :1
+data 4
+foo
+
+blob
+mark :2
+data 3
+hi
+
+reset refs/heads/master
+commit refs/heads/master
+mark :3
+author A U Thor <author@example.com> 1112912713 -0700
+committer C O Mitter <committer@example.com> 1112912713 -0700
+data 12
+Second file
+M 100644 :1 bar
+M 100644 :2 there
+
+EOF
+
+test_expect_failure 'no exact-ref revisions included' '
+       cd limit-by-paths &&
+       git fast-export master~2..master~1 > output &&
+       test_cmp output expected &&
+       cd ..
+'
+
+
 test_expect_success 'set-up a few more tags for tag export tests' '
        git checkout -f master &&
        HEAD_TREE=`git show -s --pretty=raw HEAD | grep tree | sed "s/tree //"` &&
@@ -271,8 +359,14 @@ test_expect_success 'set-up a few more tags for tag export tests' '
        git tag -a tag-obj_tag-obj -m "tagging a tag" tree_tag-obj
 '
 
+test_expect_success 'tree_tag'        '
+       mkdir result &&
+       (cd result && git init) &&
+       git fast-export tree_tag > fe-stream &&
+       (cd result && git fast-import < ../fe-stream)
+'
+
 # NEEDSWORK: not just check return status, but validate the output
-test_expect_success 'tree_tag'        'git fast-export tree_tag'
 test_expect_success 'tree_tag-obj'    'git fast-export tree_tag-obj'
 test_expect_success 'tag-obj_tag'     'git fast-export tag-obj_tag'
 test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'
index de0d5874a3d867d71eaec3cd1dde1bf2f09cfe4d..f231b355f24476372c9b89c35a41231a18e45719 100644 (file)
@@ -820,7 +820,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
 }
 
 static void print_push_status(const char *dest, struct ref *refs,
-                                                         int verbose, int porcelain)
+                             int verbose, int porcelain, int * nonfastforward)
 {
        struct ref *ref;
        int n = 0;
@@ -835,11 +835,14 @@ static void print_push_status(const char *dest, struct ref *refs,
                if (ref->status == REF_STATUS_OK)
                        n += print_one_push_status(ref, dest, n, porcelain);
 
+       *nonfastforward = 0;
        for (ref = refs; ref; ref = ref->next) {
                if (ref->status != REF_STATUS_NONE &&
                    ref->status != REF_STATUS_UPTODATE &&
                    ref->status != REF_STATUS_OK)
                        n += print_one_push_status(ref, dest, n, porcelain);
+               if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD)
+                       *nonfastforward = 1;
        }
 }
 
@@ -997,7 +1000,8 @@ int transport_set_option(struct transport *transport,
 }
 
 int transport_push(struct transport *transport,
-                  int refspec_nr, const char **refspec, int flags)
+                  int refspec_nr, const char **refspec, int flags,
+                  int * nonfastforward)
 {
        verify_remote_names(refspec_nr, refspec);
 
@@ -1024,7 +1028,7 @@ int transport_push(struct transport *transport,
 
                ret = transport->push_refs(transport, remote_refs, flags);
 
-               print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);
+               print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain, nonfastforward);
 
                if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
                        struct ref *ref;
index 51b539778c2f63591c4f032e311372b2e9975a37..639f13dcfed434857c724293cf3f3f6b9d4d14ed 100644 (file)
@@ -68,7 +68,8 @@ int transport_set_option(struct transport *transport, const char *name,
                         const char *value);
 
 int transport_push(struct transport *connection,
-                  int refspec_nr, const char **refspec, int flags);
+                  int refspec_nr, const char **refspec, int flags,
+                  int * nonfastforward);
 
 const struct ref *transport_get_remote_refs(struct transport *transport);
 
index 48d862d3b478875c3747bdb39a8cba0068300e97..720f7a161651126872b7357173c10d69d1db7636 100644 (file)
@@ -999,7 +999,7 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
                return error("Cannot do a oneway merge of %d trees",
                             o->merge_size);
 
-       if (!a)
+       if (!a || a == o->df_conflict_entry)
                return deleted_entry(old, old, o);
 
        if (old && same(old, a)) {
index e57630e983488e5c0222dc47a5e32d6efb184762..11d9052ed86ab17b56ab86ef21b7c98095e410dc 100644 (file)
--- a/walker.c
+++ b/walker.c
@@ -245,7 +245,7 @@ void walker_targets_free(int targets, char **target, const char **write_ref)
 {
        while (targets--) {
                free(target[targets]);
-               if (write_ref && write_ref[targets])
+               if (write_ref)
                        free((char *) write_ref[targets]);
        }
 }
diff --git a/ws.c b/ws.c
index 819c797cf6f7a265c01f00033fa48fdab94a0943..59d0883c1f3a46edcbb2e45b172c9eac3b9d5e35 100644 (file)
--- a/ws.c
+++ b/ws.c
@@ -261,12 +261,11 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
        /*
         * Strip trailing whitespace
         */
-       if ((ws_rule & WS_TRAILING_SPACE) &&
-           (2 <= len && isspace(src[len-2]))) {
-               if (src[len - 1] == '\n') {
+       if (ws_rule & WS_TRAILING_SPACE) {
+               if (0 < len && src[len - 1] == '\n') {
                        add_nl_to_tail = 1;
                        len--;
-                       if (1 < len && src[len - 1] == '\r') {
+                       if (0 < len && src[len - 1] == '\r') {
                                add_cr_to_tail = !!(ws_rule & WS_CR_AT_EOL);
                                len--;
                        }
index 1ebab687f77218d1520a4527214170eeab176d31..da67c04357dfe4d3283c589f5d47be9c5f2b7fcf 100644 (file)
@@ -26,7 +26,7 @@
 
 #define XDL_MAX_COST_MIN 256
 #define XDL_HEUR_MIN_COST 256
-#define XDL_LINE_MAX (long)((1UL << (8 * sizeof(long) - 1)) - 1)
+#define XDL_LINE_MAX (long)((1UL << (CHAR_BIT * sizeof(long) - 1)) - 1)
 #define XDL_SNAKE_CNT 20
 #define XDL_K_HEUR 4