summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--Documentation/RelNotes/1.8.2.txt109
-rw-r--r--Documentation/SubmittingPatches175
-rw-r--r--Documentation/config.txt30
-rw-r--r--Documentation/git-bundle.txt9
-rw-r--r--Documentation/git-config.txt4
-rw-r--r--Documentation/git-cvsimport.txt6
-rw-r--r--Documentation/git-fast-import.txt7
-rw-r--r--Documentation/git-log.txt2
-rw-r--r--Documentation/git-push.txt9
-rw-r--r--Documentation/git-remote-testgit.txt2
-rw-r--r--Documentation/git-submodule.txt25
-rw-r--r--Documentation/git.txt23
-rw-r--r--Documentation/gitignore.txt19
-rw-r--r--Documentation/gitmodules.txt5
-rw-r--r--Documentation/mailmap.txt3
-rw-r--r--Documentation/pretty-formats.txt6
-rw-r--r--Documentation/pt_BR/gittutorial.txt675
-rw-r--r--Makefile41
-rw-r--r--advice.c9
-rw-r--r--advice.h3
-rw-r--r--archive.c3
-rw-r--r--attr.c25
-rw-r--r--builtin.h3
-rw-r--r--builtin/apply.c23
-rw-r--r--builtin/branch.c2
-rw-r--r--builtin/fast-export.c27
-rw-r--r--builtin/fmt-merge-msg.c21
-rw-r--r--builtin/log.c36
-rw-r--r--builtin/ls-files.c2
-rw-r--r--builtin/ls-tree.c2
-rw-r--r--builtin/merge.c6
-rw-r--r--builtin/push.c32
-rw-r--r--builtin/send-pack.c9
-rw-r--r--cache.h19
-rw-r--r--commit.h1
-rw-r--r--compat/fnmatch/fnmatch.c3
-rw-r--r--config.c13
-rwxr-xr-xcontrib/ciabot/ciabot.py8
-rw-r--r--contrib/completion/git-completion.bash7
-rwxr-xr-xcontrib/fast-import/import-zips.py7
-rwxr-xr-xcontrib/hg-to-git/hg-to-git.py5
-rw-r--r--contrib/p4import/git-p4import.py5
-rwxr-xr-xcontrib/remote-helpers/git-remote-bzr725
-rwxr-xr-xcontrib/remote-helpers/git-remote-hg2
-rwxr-xr-xcontrib/remote-helpers/test-bzr.sh143
-rwxr-xr-xcontrib/remote-helpers/test-hg-bidi.sh2
-rwxr-xr-xcontrib/svn-fe/svnrdump_sim.py4
-rw-r--r--ctype.c15
-rw-r--r--dir.c68
-rw-r--r--dir.h9
-rw-r--r--fsck.c15
-rw-r--r--git-compat-util.h29
-rwxr-xr-xgit-p4.py8
-rw-r--r--git-rebase--am.sh49
-rwxr-xr-xgit-remote-testgit90
-rw-r--r--git-remote-testpy.py (renamed from git-remote-testgit.py)7
-rwxr-xr-xgit-submodule.sh51
-rw-r--r--git.c8
-rw-r--r--git_remote_helpers/git/__init__.py5
-rw-r--r--git_remote_helpers/git/importer.py2
-rwxr-xr-xgitweb/gitweb.perl2
-rw-r--r--http-push.c23
-rw-r--r--imap-send.c157
-rw-r--r--log-tree.c1
-rw-r--r--mailmap.c138
-rw-r--r--parse-options.c18
-rw-r--r--parse-options.h4
-rw-r--r--po/de.po484
-rw-r--r--pretty.c13
-rw-r--r--remote.c96
-rw-r--r--run-command.c2
-rw-r--r--send-pack.c1
-rw-r--r--sequencer.c20
-rw-r--r--strbuf.c26
-rw-r--r--strbuf.h6
-rw-r--r--t/Makefile9
-rwxr-xr-xt/check-non-portable-shell.pl27
-rwxr-xr-xt/t0003-attributes.sh37
-rwxr-xr-xt/t1020-subdirectory.sh12
-rwxr-xr-xt/t1402-check-ref-format.sh6
-rwxr-xr-xt/t1450-fsck.sh31
-rwxr-xr-xt/t1505-rev-parse-last.sh18
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh18
-rwxr-xr-xt/t3070-wildmatch.sh195
-rwxr-xr-xt/t3404-rebase-interactive.sh6
-rwxr-xr-xt/t3501-revert-cherry-pick.sh9
-rwxr-xr-xt/t3506-cherry-pick-ff.sh8
-rwxr-xr-xt/t3507-cherry-pick-conflict.sh6
-rwxr-xr-xt/t3508-cherry-pick-many-commits.sh8
-rwxr-xr-xt/t3510-cherry-pick-sequence.sh6
-rwxr-xr-xt/t4014-format-patch.sh42
-rwxr-xr-xt/t4203-mailmap.sh98
-rwxr-xr-xt/t5002-archive-attr-pattern.sh57
-rwxr-xr-xt/t5516-fetch-push.sh44
-rwxr-xr-xt/t5535-fetch-push-symref.sh42
-rwxr-xr-xt/t5800-remote-testpy.sh (renamed from t/t5800-remote-helpers.sh)14
-rwxr-xr-xt/t5801-remote-helpers.sh169
-rwxr-xr-xt/t6006-rev-list-format.sh63
-rwxr-xr-xt/t6030-bisect-porcelain.sh4
-rwxr-xr-xt/t6130-pathspec-noglob.sh68
-rwxr-xr-xt/t7400-submodule-basic.sh1
-rwxr-xr-xt/t7406-submodule-update.sh31
-rwxr-xr-xt/t7505-prepare-commit-msg-hook.sh14
-rwxr-xr-xt/t9020-remote-svn.sh4
-rwxr-xr-xt/t9350-fast-export.sh65
-rwxr-xr-xt/t9810-git-p4-rcs.sh24
-rw-r--r--t/test-lib-functions.sh7
-rw-r--r--test-wildmatch.c22
-rw-r--r--transport-helper.c6
-rw-r--r--transport.c25
-rw-r--r--transport.h10
-rw-r--r--tree-walk.c77
-rw-r--r--unpack-trees.c2
-rw-r--r--usage.c1
-rw-r--r--wildmatch.c235
-rw-r--r--wildmatch.h9
-rw-r--r--wrapper.c10
118 files changed, 3740 insertions, 1450 deletions
diff --git a/.gitignore b/.gitignore
index f702415c12..aa258a6bcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,8 @@
/GIT-BUILD-OPTIONS
/GIT-CFLAGS
/GIT-LDFLAGS
-/GIT-GUI-VARS
/GIT-PREFIX
+/GIT-PYTHON-VARS
/GIT-SCRIPT-DEFINES
/GIT-USER-AGENT
/GIT-VERSION-FILE
@@ -124,7 +124,7 @@
/git-remote-ftps
/git-remote-fd
/git-remote-ext
-/git-remote-testgit
+/git-remote-testpy
/git-remote-testsvn
/git-repack
/git-replace
@@ -171,7 +171,6 @@
/git-whatchanged
/git-write-tree
/git-core-*/?*
-/gitk-git/gitk-wish
/gitweb/GITWEB-BUILD-OPTIONS
/gitweb/gitweb.cgi
/gitweb/static/gitweb.js
@@ -198,6 +197,7 @@
/test-string-list
/test-subprocess
/test-svn-fe
+/test-wildmatch
/common-cmds.h
*.tar.gz
*.dsc
diff --git a/Documentation/RelNotes/1.8.2.txt b/Documentation/RelNotes/1.8.2.txt
index 6c85bf4f0f..b92a2fe18a 100644
--- a/Documentation/RelNotes/1.8.2.txt
+++ b/Documentation/RelNotes/1.8.2.txt
@@ -26,13 +26,55 @@ UI, Workflows & Features
* Output from the tests is coloured using "green is okay, yellow is
questionable, red is bad and blue is informative" scheme.
+ * In bare repositories, "git shortlog" and other commands now read
+ mailmap files from the tip of the history, to help running these
+ tools in server settings.
+
+ * Color specifiers, e.g. "%C(blue)Hello%C(reset)", used in the
+ "--format=" option of "git log" and friends can be disabled when
+ the output is not sent to a terminal by prefixing them with
+ "auto,", e.g. "%C(auto,blue)Hello%C(auto,reset)".
+
+ * Scripts can ask Git that wildcard patterns in pathspecs they give do
+ not have any significance, i.e. take them as literal strings.
+
+ * "git fetch --mirror" and fetch that uses other forms of refspec
+ with wildcard used to attempt to update a symbolic ref that match
+ the wildcard on the receiving end, which made little sense (the
+ real ref that is pointed at by the symbolic ref would be updated
+ anyway). Symbolic refs no longer are affected by such a fetch.
+
+ * "git format-patch" now detects more cases in which a whole branch
+ is being exported, and uses the description for the branch, when
+ asked to write a cover letter for the series.
+
+ * "git push" now requires "-f" to update a tag, even if it is a
+ fast-forward, as tags are meant to be fixed points.
+
+ * "git submodule" started learning a new mode to integrate with the
+ tip of the remote branch (as opposed to integrating with the commit
+ recorded in the superproject's gitlink).
+
+
Foreign Interface
- *
+ * "git fast-export" has been updated for its use in the context of
+ the remote helper interface.
+
+ * A new remote helper to interact with bzr has been added to contrib/.
+
Performance, Internal Implementation, etc.
- *
+ * "git fsck" has been taught to be pickier about entries in tree
+ objects that should not be there, e.g. ".", ".git", and "..".
+
+ * Matching paths with common forms of pathspecs that contain wildcard
+ characters has been optimized further.
+
+ * The implementation of "imap-send" has been updated to reuse xml
+ quoting code from http-push codepath.
+
Also contains minor documentation updates and code clean-ups.
@@ -49,17 +91,11 @@ details).
the GIT_DIR discovery logic to escape the ceiling.
(merge 059b379 mh/ceiling later to maint).
- * t4014, t9502 and t0200 tests had various portability issues that
- broke on OpenBSD.
- (merge 27f6342 jc/maint-test-portability later to maint).
-
- * t9020 and t3600 tests had various portability issues.
- (merge 5a02966 jc/test-portability later to maint).
-
- * t9200 runs "cvs init" on a directory that already exists, but a
- platform can configure this fail for the current user (e.g. you
- need to be in the cvsadmin group on NetBSD 6.0).
- (merge 8666df0 jc/test-cvs-no-init-in-existing-dir later to maint).
+ * When attempting to read the XDG-style $HOME/.config/git/config and
+ finding that $HOME/.config/git is a file, we gave a wrong error
+ message, instead of treating the case as "a custom config file does
+ not exist there" and moving on.
+ (merge 8f2bbe4 jn/warn-on-inaccessible-loosen later to maint).
* The behaviour visible to the end users was confusing, when they
attempt to kill a process spawned in the editor that was in turn
@@ -71,6 +107,15 @@ details).
pathname was not reported correctly on some platforms.
(merge f7be59b jc/mkstemp-more-careful-error-reporting later to maint).
+ * The attribute mechanism didn't allow limiting attributes to be
+ applied to only a single directory itself with "path/" like the
+ exclude mechanism does.
+ (merge 94bc671 ja/directory-attrs later to maint).
+
+ * "git apply" misbehaved when fixing whitespace breakages by removing
+ excess trailing blank lines.
+ (merge 5de7166 jc/apply-trailing-blank-removal later to maint).
+
* The way "git svn" asked for password using SSH_ASKPASS and
GIT_ASKPASS was not in line with the rest of the system.
(merge e9263e4 ss/svn-prompt later to maint).
@@ -91,11 +136,21 @@ details).
index, the cache-tree data structure got corrupted.
(merge eec3e7e nd/invalidate-i-t-a-cache-tree later to maint).
+ * "git merge" started calling prepare-commit-msg hook like "git
+ commit" does some time ago, but forgot to pay attention to the exit
+ status of the hook.
+ (merge 3e4141d ap/merge-stop-at-prepare-commit-msg-failure later to maint).
+
* "gitweb", when sorting by age to show repositories with new
activities first, used to sort repositories with absolutely
nothing in it early, which was not very useful.
(merge 28dae18 md/gitweb-sort-by-age later to maint).
+ * "gitweb"'s code to sanitize control characters before passing it to
+ "highlight" filter lost known-to-be-safe control characters by
+ mistake.
+ (merge 0e901d2 os/gitweb-highlight-uncaptured later to maint).
+
* When a line to be wrapped has a solid run of non space characters
whose length exactly is the wrap width, "git shortlog -w" failed
to add a newline after such a line.
@@ -104,3 +159,31 @@ details).
* Some shells do not behave correctly when IFS is unset; work it
around by explicitly setting it to the default value.
(merge 393050c jc/maint-fbsd-sh-ifs-workaround later to maint).
+
+ * Some scripted programs written in Python did not get updated when
+ PYTHON_PATH changed.
+ (cherry-pick 96a4647fca54031974cd6ad1 later to maint).
+
+ * When autoconf is used, any build on a different commit always ran
+ "config.status --recheck" even when unnecessary.
+ (merge 1226504 jn/less-reconfigure later to maint).
+
+ * We have been carrying a translated and long-unmaintained copy of an
+ old version of the tutorial; removed.
+ (merge 0a85441 ta/remove-stale-translated-tut later to maint).
+
+ * t4014, t9502 and t0200 tests had various portability issues that
+ broke on OpenBSD.
+ (merge 27f6342 jc/maint-test-portability later to maint).
+
+ * t9020 and t3600 tests had various portability issues.
+ (merge 5a02966 jc/test-portability later to maint).
+
+ * t9200 runs "cvs init" on a directory that already exists, but a
+ platform can configure this fail for the current user (e.g. you
+ need to be in the cvsadmin group on NetBSD 6.0).
+ (merge 8666df0 jc/test-cvs-no-init-in-existing-dir later to maint).
+
+ * t9020 and t9810 had a few non-portable shell script construct.
+ (merge 2797914 tb/test-t9020-no-which later to maint).
+ (merge 6f4e505 tb/test-t9810-no-sed-i later to maint).
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 75935d500d..90133d8c3b 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -1,73 +1,5 @@
-Checklist (and a short version for the impatient):
-
- Commits:
-
- - make commits of logical units
- - check for unnecessary whitespace with "git diff --check"
- before committing
- - do not check in commented out code or unneeded files
- - the first line of the commit message should be a short
- description (50 characters is the soft limit, see DISCUSSION
- in git-commit(1)), and should skip the full stop
- - it is also conventional in most cases to prefix the
- first line with "area: " where the area is a filename
- or identifier for the general area of the code being
- modified, e.g.
- . archive: ustar header checksum is computed unsigned
- . git-cherry-pick.txt: clarify the use of revision range notation
- (if in doubt which identifier to use, run "git log --no-merges"
- on the files you are modifying to see the current conventions)
- - the body should provide a meaningful commit message, which:
- . explains the problem the change tries to solve, iow, what
- is wrong with the current code without the change.
- . justifies the way the change solves the problem, iow, why
- the result with the change is better.
- . alternate solutions considered but discarded, if any.
- - describe changes in imperative mood, e.g. "make xyzzy do frotz"
- instead of "[This patch] makes xyzzy do frotz" or "[I] changed
- xyzzy to do frotz", as if you are giving orders to the codebase
- to change its behaviour.
- - try to make sure your explanation can be understood without
- external resources. Instead of giving a URL to a mailing list
- archive, summarize the relevant points of the discussion.
- - add a "Signed-off-by: Your Name <you@example.com>" line to the
- commit message (or just use the option "-s" when committing)
- to confirm that you agree to the Developer's Certificate of Origin
- - make sure that you have tests for the bug you are fixing
- - make sure that the test suite passes after your commit
-
- Patch:
-
- - use "git format-patch -M" to create the patch
- - do not PGP sign your patch
- - do not attach your patch, but read in the mail
- body, unless you cannot teach your mailer to
- leave the formatting of the patch alone.
- - be careful doing cut & paste into your mailer, not to
- corrupt whitespaces.
- - provide additional information (which is unsuitable for
- the commit message) between the "---" and the diffstat
- - if you change, add, or remove a command line option or
- make some other user interface change, the associated
- documentation should be updated as well.
- - if your name is not writable in ASCII, make sure that
- you send off a message in the correct encoding.
- - send the patch to the list (git@vger.kernel.org) and the
- maintainer (gitster@pobox.com) if (and only if) the patch
- is ready for inclusion. If you use git-send-email(1),
- please test it first by sending email to yourself.
- - see below for instructions specific to your mailer
-
-Long version:
-
-I started reading over the SubmittingPatches document for Linux
-kernel, primarily because I wanted to have a document similar to
-it for the core GIT to make sure people understand what they are
-doing when they write "Signed-off-by" line.
-
-But the patch submission requirements are a lot more relaxed
-here on the technical/contents front, because the core GIT is
-thousand times smaller ;-). So here is only the relevant bits.
+Here are some guidelines for people who want to contribute their code
+to this software.
(0) Decide what to base your work on.
@@ -94,6 +26,10 @@ change is relevant to.
wait until some of the dependent topics graduate to 'master', and
rebase your work.
+ - Some parts of the system have dedicated maintainers with their own
+ repositories (see the section "Subsystems" below). Changes to
+ these parts should be based on their trees.
+
To find the tip of a topic branch, run "git log --first-parent
master..pu" and look for the merge commit. The second parent of this
commit is the tip of the topic branch.
@@ -121,13 +57,53 @@ change, the approach taken by the change, and if relevant how this
differs substantially from the prior version, are all good things
to have.
+Make sure that you have tests for the bug you are fixing.
+
+When adding a new feature, make sure that you have new tests to show
+the feature triggers the new behaviour when it should, and to show the
+feature does not trigger when it shouldn't. Also make sure that the
+test suite passes after your commit. Do not forget to update the
+documentation to describe the updated behaviour.
+
Oh, another thing. I am picky about whitespaces. Make sure your
changes do not trigger errors with the sample pre-commit hook shipped
in templates/hooks--pre-commit. To help ensure this does not happen,
run git diff --check on your changes before you commit.
-(2) Generate your patch using git tools out of your commits.
+(2) Describe your changes well.
+
+The first line of the commit message should be a short description (50
+characters is the soft limit, see DISCUSSION in git-commit(1)), and
+should skip the full stop. It is also conventional in most cases to
+prefix the first line with "area: " where the area is a filename or
+identifier for the general area of the code being modified, e.g.
+
+ . archive: ustar header checksum is computed unsigned
+ . git-cherry-pick.txt: clarify the use of revision range notation
+
+If in doubt which identifier to use, run "git log --no-merges" on the
+files you are modifying to see the current conventions.
+
+The body should provide a meaningful commit message, which:
+
+ . explains the problem the change tries to solve, iow, what is wrong
+ with the current code without the change.
+
+ . justifies the way the change solves the problem, iow, why the
+ result with the change is better.
+
+ . alternate solutions considered but discarded, if any.
+
+Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
+instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
+to do frotz", as if you are giving orders to the codebase to change
+its behaviour. Try to make sure your explanation can be understood
+without external resources. Instead of giving a URL to a mailing list
+archive, summarize the relevant points of the discussion.
+
+
+(3) Generate your patch using git tools out of your commits.
git based diff tools generate unidiff which is the preferred format.
@@ -135,22 +111,27 @@ You do not have to be afraid to use -M option to "git diff" or
"git format-patch", if your patch involves file renames. The
receiving end can handle them just fine.
-Please make sure your patch does not include any extra files
-which do not belong in a patch submission. Make sure to review
+Please make sure your patch does not add commented out debugging code,
+or include any extra files which do not relate to what your patch
+is trying to achieve. Make sure to review
your patch after generating it, to ensure accuracy. Before
sending out, please make sure it cleanly applies to the "master"
branch head. If you are preparing a work based on "next" branch,
that is fine, but please mark it as such.
-(3) Sending your patches.
+(4) Sending your patches.
People on the git mailing list need to be able to read and
comment on the changes you are submitting. It is important for
a developer to be able to "quote" your changes, using standard
e-mail tools, so that they may comment on specific portions of
your code. For this reason, all patches should be submitted
-"inline". WARNING: Be wary of your MUAs word-wrap
+"inline". If your log message (including your name on the
+Signed-off-by line) is not writable in ASCII, make sure that
+you send off a message in the correct encoding.
+
+WARNING: Be wary of your MUAs word-wrap
corrupting your patch. Do not cut-n-paste your patch; you can
lose tabs that way if you are not careful.
@@ -203,19 +184,25 @@ patch, format it as "multipart/signed", not a text/plain message
that starts with '-----BEGIN PGP SIGNED MESSAGE-----'. That is
not a text/plain, it's something else.
-Unless your patch is a very trivial and an obviously correct one,
-first send it with "To:" set to the mailing list, with "cc:" listing
+Send your patch with "To:" set to the mailing list, with "cc:" listing
people who are involved in the area you are touching (the output from
"git blame $path" and "git shortlog --no-merges $path" would help to
-identify them), to solicit comments and reviews. After the list
-reached a consensus that it is a good idea to apply the patch, re-send
-it with "To:" set to the maintainer and optionally "cc:" the list for
-inclusion. Do not forget to add trailers such as "Acked-by:",
-"Reviewed-by:" and "Tested-by:" after your "Signed-off-by:" line as
-necessary.
+identify them), to solicit comments and reviews.
+After the list reached a consensus that it is a good idea to apply the
+patch, re-send it with "To:" set to the maintainer [*1*] and "cc:" the
+list [*2*] for inclusion.
-(4) Sign your work
+Do not forget to add trailers such as "Acked-by:", "Reviewed-by:" and
+"Tested-by:" lines as necessary to credit people who helped your
+patch.
+
+ [Addresses]
+ *1* The current maintainer: gitster@pobox.com
+ *2* The mailing list: git@vger.kernel.org
+
+
+(5) Sign your work
To improve tracking of who did what, we've borrowed the
"sign-off" procedure from the Linux kernel project on patches
@@ -286,6 +273,26 @@ You can also create your own tag or use one that's in common usage
such as "Thanks-to:", "Based-on-patch-by:", or "Mentored-by:".
------------------------------------------------
+Subsystems with dedicated maintainers
+
+Some parts of the system have dedicated maintainers with their own
+repositories.
+
+ - git-gui/ comes from git-gui project, maintained by Pat Thoyts:
+
+ git://repo.or.cz/git-gui.git
+
+ - gitk-git/ comes from Paul Mackerras's gitk project:
+
+ git://ozlabs.org/~paulus/gitk
+
+ - po/ comes from the localization coordinator, Jiang Xin:
+
+ https://github.com/git-l10n/git-po/
+
+Patches to these parts should be based on their trees.
+
+------------------------------------------------
An ideal patch flow
Here is an ideal patch flow for this project the current maintainer
diff --git a/Documentation/config.txt b/Documentation/config.txt
index bf8f911e1f..d5809e0e8c 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -140,10 +140,11 @@ advice.*::
can tell Git that you do not need help by setting these to 'false':
+
--
- pushNonFastForward::
+ pushUpdateRejected::
Set this variable to 'false' if you want to disable
- 'pushNonFFCurrent', 'pushNonFFDefault', and
- 'pushNonFFMatching' simultaneously.
+ 'pushNonFFCurrent', 'pushNonFFDefault',
+ 'pushNonFFMatching', and 'pushAlreadyExists'
+ simultaneously.
pushNonFFCurrent::
Advice shown when linkgit:git-push[1] fails due to a
non-fast-forward update to the current branch.
@@ -158,6 +159,9 @@ advice.*::
'matching refs' explicitly (i.e. you used ':', or
specified a refspec that isn't your current branch) and
it resulted in a non-fast-forward error.
+ pushAlreadyExists::
+ Shown when linkgit:git-push[1] rejects an update that
+ does not qualify for fast-forwarding (e.g., a tag.)
statusHints::
Show directions on how to proceed from the current
state in the output of linkgit:git-status[1], in
@@ -735,6 +739,12 @@ branch.<name>.rebase::
it unless you understand the implications (see linkgit:git-rebase[1]
for details).
+branch.<name>.description::
+ Branch description, can be edited with
+ `git branch --edit-description`. Branch description is
+ automatically added in the format-patch cover letter or
+ request-pull summary.
+
browser.<tool>.cmd::
Specify the command to invoke the specified browser. The
specified command is evaluated in shell with the URLs passed
@@ -1517,6 +1527,14 @@ mailmap.file::
subdirectory, or somewhere outside of the repository itself.
See linkgit:git-shortlog[1] and linkgit:git-blame[1].
+mailmap.blob::
+ Like `mailmap.file`, but consider the value as a reference to a
+ blob in the repository. If both `mailmap.file` and
+ `mailmap.blob` are given, both are parsed, with entries from
+ `mailmap.file` taking precedence. In a bare repository, this
+ defaults to `HEAD:.mailmap`. In a non-bare repository, it
+ defaults to empty.
+
man.viewer::
Specify the programs that may be used to display help in the
'man' format. See linkgit:git-help[1].
@@ -1995,6 +2013,12 @@ submodule.<name>.update::
URL and other values found in the `.gitmodules` file. See
linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
+submodule.<name>.branch::
+ The remote branch name for a submodule, used by `git submodule
+ update --remote`. Set this option to override the value found in
+ the `.gitmodules` file. See linkgit:git-submodule[1] and
+ linkgit:gitmodules[5] for details.
+
submodule.<name>.fetchRecurseSubmodules::
This option can be used to control recursive fetching of this
submodule. It can be overridden by using the --[no-]recurse-submodules
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index 16a6b0aceb..bc023cc5f3 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -112,13 +112,12 @@ machineA$ git bundle create file.bundle master
machineA$ git tag -f lastR2bundle master
----------------
-Then you transfer file.bundle to the target machine B. If you are creating
-the repository on machine B, then you can clone from the bundle as if it
-were a remote repository instead of creating an empty repository and then
-pulling or fetching objects from the bundle:
+Then you transfer file.bundle to the target machine B. Because this
+bundle does not require any existing object to be extracted, you can
+create a new repository on machine B by cloning from it:
----------------
-machineB$ git clone /home/me/tmp/file.bundle R2
+machineB$ git clone -b master /home/me/tmp/file.bundle R2
----------------
This will define a remote called "origin" in the resulting repository that
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index eaea079165..9ae2508f3f 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -240,6 +240,10 @@ GIT_CONFIG::
Using the "--global" option forces this to ~/.gitconfig. Using the
"--system" option forces this to $(prefix)/etc/gitconfig.
+GIT_CONFIG_NOSYSTEM::
+ Whether to skip reading settings from the system-wide
+ $(prefix)/etc/gitconfig file. See linkgit:git[1] for details.
+
See also <<FILES>>.
diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt
index 98d9881d7e..9d5353e8be 100644
--- a/Documentation/git-cvsimport.txt
+++ b/Documentation/git-cvsimport.txt
@@ -213,11 +213,9 @@ Problems related to tags:
* Multiple tags on the same revision are not imported.
If you suspect that any of these issues may apply to the repository you
-want to import consider using these alternative tools which proved to be
-more stable in practice:
+want to imort, consider using cvs2git:
-* cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org`
-* parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs`
+* cvs2git (part of cvs2svn), `http://subversion.apache.org/`
GIT
---
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 68bca1a29d..3da5cc272a 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -39,10 +39,6 @@ OPTIONS
See ``Date Formats'' below for details about which formats
are supported, and their syntax.
--- done::
- Terminate with error if there is no 'done' command at the
- end of the stream.
-
--force::
Force updating modified existing branches, even if doing
so would cause commits to be lost (as the new commit does
@@ -108,7 +104,8 @@ OPTIONS
output.
--done::
- Require a `done` command at the end of the stream.
+ Terminate with error if there is no `done` command at the
+ end of the stream.
This option might be useful for detecting errors that
cause the frontend to terminate before it has started to
write a stream.
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 585dac40ba..08a185db7f 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -167,7 +167,7 @@ log.showroot::
`git log -p` output would be shown without a diff attached.
The default is `true`.
-mailmap.file::
+mailmap.*::
See linkgit:git-shortlog[1].
notes.displayRef::
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 8b637d339f..c964b796be 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -51,10 +51,11 @@ be named. If `:`<dst> is omitted, the same ref as <src> will be
updated.
+
The object referenced by <src> is used to update the <dst> reference
-on the remote side, but by default this is only allowed if the
-update can fast-forward <dst>. By having the optional leading `+`,
-you can tell git to update the <dst> ref even when the update is not a
-fast-forward. This does *not* attempt to merge <src> into <dst>. See
+on the remote side. By default this is only allowed if <dst> is not
+a tag (annotated or lightweight), and then only if it can fast-forward
+<dst>. By having the optional leading `+`, you can tell git to update
+the <dst> ref even if it is not allowed by default (e.g., it is not a
+fast-forward.) This does *not* attempt to merge <src> into <dst>. See
EXAMPLES below for details.
+
`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
diff --git a/Documentation/git-remote-testgit.txt b/Documentation/git-remote-testgit.txt
index 2a67d456a3..612a625ced 100644
--- a/Documentation/git-remote-testgit.txt
+++ b/Documentation/git-remote-testgit.txt
@@ -19,7 +19,7 @@ testcase for the remote-helper functionality, and as an example to
show remote-helper authors one possible implementation.
The best way to learn more is to read the comments and source code in
-'git-remote-testgit.py'.
+'git-remote-testgit'.
SEE ALSO
--------
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index b1de3bade7..b1996f1a63 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -13,7 +13,7 @@ SYNOPSIS
[--reference <repository>] [--] <repository> [<path>]
'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
'git submodule' [--quiet] init [--] [<path>...]
-'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
+'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch] [--rebase]
[--reference <repository>] [--merge] [--recursive] [--] [<path>...]
'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
[commit] [--] [<path>...]
@@ -208,6 +208,8 @@ OPTIONS
-b::
--branch::
Branch of repository to add as submodule.
+ The name of the branch is recorded as `submodule.<path>.branch` in
+ `.gitmodules` for `update --remote`.
-f::
--force::
@@ -236,6 +238,27 @@ OPTIONS
(the default). This limit only applies to modified submodules. The
size is always limited to 1 for added/deleted/typechanged submodules.
+--remote::
+ This option is only valid for the update command. Instead of using
+ the superproject's recorded SHA-1 to update the submodule, use the
+ status of the submodule's remote tracking branch. The remote used
+ is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
+ The remote branch used defaults to `master`, but the branch name may
+ be overridden by setting the `submodule.<name>.branch` option in
+ either `.gitmodules` or `.git/config` (with `.git/config` taking
+ precedence).
++
+This works for any of the supported update procedures (`--checkout`,
+`--rebase`, etc.). The only change is the source of the target SHA-1.
+For example, `submodule update --remote --merge` will merge upstream
+submodule changes into the submodules, while `submodule update
+--merge` will merge superproject gitlink changes into the submodules.
++
+In order to ensure a current tracking branch state, `update --remote`
+fetches the submodule's remote repository before calculating the
+SHA-1. If you don't want to fetch, you should use `submodule update
+--remote --no-fetch`.
+
-N::
--no-fetch::
This option is only valid for the update command.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 7a3f03b5ce..c03b7adc97 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -428,6 +428,11 @@ help ...`.
Do not use replacement refs to replace git objects. See
linkgit:git-replace[1] for more information.
+--literal-pathspecs::
+ Treat pathspecs literally, rather than as glob patterns. This is
+ equivalent to setting the `GIT_LITERAL_PATHSPECS` environment
+ variable to `1`.
+
GIT COMMANDS
------------
@@ -772,6 +777,14 @@ for further details.
and read the password from its STDOUT. See also the 'core.askpass'
option in linkgit:git-config[1].
+'GIT_CONFIG_NOSYSTEM'::
+ Whether to skip reading settings from the system-wide
+ `$(prefix)/etc/gitconfig` file. This environment variable can
+ be used along with `$HOME` and `$XDG_CONFIG_HOME` to create a
+ predictable environment for a picky script, or you can set it
+ temporarily to avoid using a buggy `/etc/gitconfig` file while
+ waiting for someone with sufficient permissions to fix it.
+
'GIT_FLUSH'::
If this environment variable is set to "1", then commands such
as 'git blame' (in incremental mode), 'git rev-list', 'git log',
@@ -796,6 +809,16 @@ for further details.
as a file path and will try to write the trace messages
into it.
+GIT_LITERAL_PATHSPECS::
+ Setting this variable to `1` will cause git to treat all
+ pathspecs literally, rather than as glob patterns. For example,
+ running `GIT_LITERAL_PATHSPECS=1 git log -- '*.c'` will search
+ for commits that touch the path `*.c`, not any paths that the
+ glob `*.c` matches. You might want this if you are feeding
+ literal paths to git (e.g., paths previously given to you by
+ `git ls-tree`, `--raw` diff output, etc).
+
+
Discussion[[Discussion]]
------------------------
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index 1b82fe1969..91a6438031 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -108,6 +108,25 @@ PATTERN FORMAT
For example, "/{asterisk}.c" matches "cat-file.c" but not
"mozilla-sha1/sha1.c".
+Two consecutive asterisks ("`**`") in patterns matched against
+full pathname may have special meaning:
+
+ - A leading "`**`" followed by a slash means match in all
+ directories. For example, "`**/foo`" matches file or directory
+ "`foo`" anywhere, the same as pattern "`foo`". "**/foo/bar"
+ matches file or directory "`bar`" anywhere that is directly
+ under directory "`foo`".
+
+ - A trailing "/**" matches everything inside. For example,
+ "abc/**" matches all files inside directory "abc", relative
+ to the location of the `.gitignore` file, with infinite depth.
+
+ - A slash followed by two consecutive asterisks then a slash
+ matches zero or more directories. For example, "`a/**/b`"
+ matches "`a/b`", "`a/x/b`", "`a/x/y/b`" and so on.
+
+ - Other consecutive asterisks are considered invalid.
+
NOTES
-----
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index ab3e91c054..52d7ae4313 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -49,6 +49,11 @@ submodule.<name>.update::
This config option is overridden if 'git submodule update' is given
the '--merge', '--rebase' or '--checkout' options.
+submodule.<name>.branch::
+ A remote branch name for tracking updates in the upstream submodule.
+ If the option is not specified, it defaults to 'master'. See the
+ `--remote` documentation in linkgit:git-submodule[1] for details.
+
submodule.<name>.fetchRecurseSubmodules::
This option can be used to control recursive fetching of this
submodule. If this option is also present in the submodules entry in
diff --git a/Documentation/mailmap.txt b/Documentation/mailmap.txt
index dd89fca3f8..4a8c276529 100644
--- a/Documentation/mailmap.txt
+++ b/Documentation/mailmap.txt
@@ -1,5 +1,6 @@
If the file `.mailmap` exists at the toplevel of the repository, or at
-the location pointed to by the mailmap.file configuration option, it
+the location pointed to by the mailmap.file or mailmap.blob
+configuration options, it
is used to map author and committer names and email addresses to
canonical real names and email addresses.
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index d9eddedc72..105f18a6f9 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -144,7 +144,11 @@ The placeholders are:
- '%Cgreen': switch color to green
- '%Cblue': switch color to blue
- '%Creset': reset color
-- '%C(...)': color specification, as described in color.branch.* config option
+- '%C(...)': color specification, as described in color.branch.* config option;
+ adding `auto,` at the beginning will emit color only when colors are
+ enabled for log output (by `color.diff`, `color.ui`, or `--color`, and
+ respecting the `auto` settings of the former if we are going to a
+ terminal)
- '%m': left, right or boundary mark
- '%n': newline
- '%%': a raw '%'
diff --git a/Documentation/pt_BR/gittutorial.txt b/Documentation/pt_BR/gittutorial.txt
deleted file mode 100644
index beba065252..0000000000
--- a/Documentation/pt_BR/gittutorial.txt
+++ /dev/null
@@ -1,675 +0,0 @@
-gittutorial(7)
-==============
-
-NOME
-----
-gittutorial - Um tutorial de introdução ao git (para versão 1.5.1 ou mais nova)
-
-SINOPSE
---------
-git *
-
-DESCRIÇÃO
------------
-
-Este tutorial explica como importar um novo projeto para o git,
-adicionar mudanças a ele, e compartilhar mudanças com outros
-desenvolvedores.
-
-Se, ao invés disso, você está interessado primariamente em usar git para
-obter um projeto, por exemplo, para testar a última versão, você pode
-preferir começar com os primeiros dois capítulos de
-link:user-manual.html[O Manual do Usuário Git].
-
-Primeiro, note que você pode obter documentação para um comando como
-`git log --graph` com:
-
-------------------------------------------------
-$ man git-log
-------------------------------------------------
-
-ou:
-
-------------------------------------------------
-$ git help log
-------------------------------------------------
-
-Com a última forma, você pode usar o visualizador de manual de sua
-escolha; veja linkgit:git-help[1] para maior informação.
-
-É uma boa idéia informar ao git seu nome e endereço público de email
-antes de fazer qualquer operação. A maneira mais fácil de fazê-lo é:
-
-------------------------------------------------
-$ git config --global user.name "Seu Nome Vem Aqui"
-$ git config --global user.email voce@seudominio.exemplo.com
-------------------------------------------------
-
-
-Importando um novo projeto
------------------------
-
-Assuma que você tem um tarball project.tar.gz com seu trabalho inicial.
-Você pode colocá-lo sob controle de revisão git da seguinte forma:
-
-------------------------------------------------
-$ tar xzf project.tar.gz
-$ cd project
-$ git init
-------------------------------------------------
-
-Git irá responder
-
-------------------------------------------------
-Initialized empty Git repository in .git/
-------------------------------------------------
-
-Agora que você iniciou seu diretório de trabalho, você deve ter notado que um
-novo diretório foi criado com o nome de ".git".
-
-A seguir, diga ao git para gravar um instantâneo do conteúdo de todos os
-arquivos sob o diretório atual (note o '.'), com 'git-add':
-
-------------------------------------------------
-$ git add .
-------------------------------------------------
-
-Este instantâneo está agora armazenado em uma área temporária que o git
-chama de "index" ou índice. Você pode armazenar permanentemente o
-conteúdo do índice no repositório com 'git-commit':
-
-------------------------------------------------
-$ git commit
-------------------------------------------------
-
-Isto vai te pedir por uma mensagem de commit. Você agora gravou sua
-primeira versão de seu projeto no git.
-
-Fazendo mudanças
---------------
-
-Modifique alguns arquivos, e, então, adicione seu conteúdo atualizado ao
-índice:
-
-------------------------------------------------
-$ git add file1 file2 file3
-------------------------------------------------
-
-Você está agora pronto para fazer o commit. Você pode ver o que está
-para ser gravado usando 'git-diff' com a opção --cached:
-
-------------------------------------------------
-$ git diff --cached
-------------------------------------------------
-
-(Sem --cached, o comando 'git-diff' irá te mostrar quaisquer mudanças
-que você tenha feito mas ainda não adicionou ao índice.) Você também
-pode obter um breve sumário da situação com 'git-status':
-
-------------------------------------------------
-$ git status
-# On branch master
-# Changes to be committed:
-# (use "git reset HEAD <file>..." to unstage)
-#
-# modified: file1
-# modified: file2
-# modified: file3
-#
-------------------------------------------------
-
-Se você precisar fazer qualquer outro ajuste, faça-o agora, e, então,
-adicione qualquer conteúdo modificado ao índice. Finalmente, grave suas
-mudanças com:
-
-------------------------------------------------
-$ git commit
-------------------------------------------------
-
-Ao executar esse comando, ele irá te pedir uma mensagem descrevendo a mudança,
-e, então, irá gravar a nova versão do projeto.
-
-Alternativamente, ao invés de executar 'git-add' antes, você pode usar
-
-------------------------------------------------
-$ git commit -a
-------------------------------------------------
-
-o que irá automaticamente notar quaisquer arquivos modificados (mas não
-novos), adicioná-los ao índices, e gravar, tudo em um único passo.
-
-Uma nota em mensagens de commit: Apesar de não ser exigido, é uma boa
-idéia começar a mensagem com uma simples e curta (menos de 50
-caracteres) linha sumarizando a mudança, seguida de uma linha em branco
-e, então, uma descrição mais detalhada. Ferramentas que transformam
-commits em email, por exemplo, usam a primeira linha no campo de
-cabeçalho "Subject:" e o resto no corpo.
-
-Git rastreia conteúdo, não arquivos
-----------------------------
-
-Muitos sistemas de controle de revisão provêem um comando `add` que diz
-ao sistema para começar a rastrear mudanças em um novo arquivo. O
-comando `add` do git faz algo mais simples e mais poderoso: 'git-add' é
-usado tanto para arquivos novos e arquivos recentemente modificados, e
-em ambos os casos, ele tira o instantâneo dos arquivos dados e armazena
-o conteúdo no índice, pronto para inclusão do próximo commit.
-
-Visualizando a história do projeto
------------------------
-
-Em qualquer ponto você pode visualizar a história das suas mudanças
-usando
-
-------------------------------------------------
-$ git log
-------------------------------------------------
-
-Se você também quiser ver a diferença completa a cada passo, use
-
-------------------------------------------------
-$ git log -p
-------------------------------------------------
-
-Geralmente, uma visão geral da mudança é útil para ter a sensação de
-cada passo
-
-------------------------------------------------
-$ git log --stat --summary
-------------------------------------------------
-
-Gerenciando "branches"/ramos
------------------
-
-Um simples repositório git pode manter múltiplos ramos de
-desenvolvimento. Para criar um novo ramo chamado "experimental", use
-
-------------------------------------------------
-$ git branch experimental
-------------------------------------------------
-
-Se você executar agora
-
-------------------------------------------------
-$ git branch
-------------------------------------------------
-
-você vai obter uma lista de todos os ramos existentes:
-
-------------------------------------------------
- experimental
-* master
-------------------------------------------------
-
-O ramo "experimental" é o que você acaba de criar, e o ramo "master" é o
-ramo padrão que foi criado pra você automaticamente. O asterisco marca
-o ramo em que você está atualmente; digite
-
-------------------------------------------------
-$ git checkout experimental
-------------------------------------------------
-
-para mudar para o ramo experimental. Agora edite um arquivo, grave a
-mudança, e mude de volta para o ramo master:
-
-------------------------------------------------
-(edita arquivo)
-$ git commit -a
-$ git checkout master
-------------------------------------------------
-
-Verifique que a mudança que você fez não está mais visível, já que ela
-foi feita no ramo experimental e você está de volta ao ramo master.
-
-Você pode fazer uma mudança diferente no ramo master:
-
-------------------------------------------------
-(edit file)
-$ git commit -a
-------------------------------------------------
-
-neste ponto, os dois ramos divergiram, com diferentes mudanças feitas em
-cada um. Para unificar as mudanças feitas no experimental para o
-master, execute
-
-------------------------------------------------
-$ git merge experimental
-------------------------------------------------
-
-Se as mudanças não conflitarem, estará pronto. Se existirem conflitos,
-marcadores serão deixados nos arquivos problemáticos exibindo o
-conflito;
-
-------------------------------------------------
-$ git diff
-------------------------------------------------
-
-vai exibir isto. Após você editar os arquivos para resolver os
-conflitos,
-
-------------------------------------------------
-$ git commit -a
-------------------------------------------------
-
-irá gravar o resultado da unificação. Finalmente,
-
-------------------------------------------------
-$ gitk
-------------------------------------------------
-
-vai mostrar uma bela representação gráfica da história resultante.
-
-Neste ponto você pode remover seu ramo experimental com
-
-------------------------------------------------
-$ git branch -d experimental
-------------------------------------------------
-
-Este comando garante que as mudanças no ramo experimental já estão no
-ramo atual.
-
-Se você desenvolve em um ramo ideia-louca, e se arrepende, você pode
-sempre remover o ramo com
-
--------------------------------------
-$ git branch -D ideia-louca
--------------------------------------
-
-Ramos são baratos e fáceis, então isto é uma boa maneira de experimentar
-alguma coisa.
-
-Usando git para colaboração
----------------------------
-
-Suponha que Alice começou um novo projeto com um repositório git em
-/home/alice/project, e que Bob, que tem um diretório home na mesma
-máquina, quer contribuir.
-
-Bob começa com:
-
-------------------------------------------------
-bob$ git clone /home/alice/project myrepo
-------------------------------------------------
-
-Isso cria um novo diretório "myrepo" contendo um clone do repositório de
-Alice. O clone está no mesmo pé que o projeto original, possuindo sua
-própria cópia da história do projeto original.
-
-Bob então faz algumas mudanças e as grava:
-
-------------------------------------------------
-(editar arquivos)
-bob$ git commit -a
-(repetir conforme necessário)
-------------------------------------------------
-
-Quanto está pronto, ele diz a Alice para puxar as mudanças do
-repositório em /home/bob/myrepo. Ela o faz com:
-
-------------------------------------------------
-alice$ cd /home/alice/project
-alice$ git pull /home/bob/myrepo master
-------------------------------------------------
-
-Isto unifica as mudanças do ramo "master" do Bob ao ramo atual de Alice.
-Se Alice fez suas próprias mudanças no intervalo, ela, então, pode
-precisar corrigir manualmente quaisquer conflitos. (Note que o argumento
-"master" no comando acima é, de fato, desnecessário, já que é o padrão.)
-
-O comando "pull" executa, então, duas operações: ele obtém mudanças de
-um ramo remoto, e, então, as unifica no ramo atual.
-
-Note que, em geral, Alice gostaria que suas mudanças locais fossem
-gravadas antes de iniciar este "pull". Se o trabalho de Bob conflita
-com o que Alice fez desde que suas histórias se ramificaram, Alice irá
-usar seu diretório de trabalho e o índice para resolver conflitos, e
-mudanças locais existentes irão interferir com o processo de resolução
-de conflitos (git ainda irá realizar a obtenção mas irá se recusar a
-unificar --- Alice terá que se livrar de suas mudanças locais de alguma
-forma e puxar de novo quando isso acontecer).
-
-Alice pode espiar o que Bob fez sem unificar primeiro, usando o comando
-"fetch"; isto permite Alice inspecionar o que Bob fez, usando um símbolo
-especial "FETCH_HEAD", com o fim de determinar se ele tem alguma coisa
-que vale puxar, assim:
-
-------------------------------------------------
-alice$ git fetch /home/bob/myrepo master
-alice$ git log -p HEAD..FETCH_HEAD
-------------------------------------------------
-
-Esta operação é segura mesmo se Alice tem mudanças locais não gravadas.
-A notação de intervalo "HEAD..FETCH_HEAD" significa mostrar tudo que é
-alcançável de FETCH_HEAD mas exclua tudo o que é alcançável de HEAD.
-Alice já sabe tudo que leva a seu estado atual (HEAD), e revisa o que Bob
-tem em seu estado (FETCH_HEAD) que ela ainda não viu com esse comando.
-
-Se Alice quer visualizar o que Bob fez desde que suas histórias se
-ramificaram, ela pode disparar o seguinte comando:
-
-------------------------------------------------
-$ gitk HEAD..FETCH_HEAD
-------------------------------------------------
-
-Isto usa a mesma notação de intervalo que vimos antes com 'git log'.
-
-Alice pode querer ver o que ambos fizeram desde que ramificaram. Ela
-pode usar a forma com três pontos ao invés da forma com dois pontos:
-
-------------------------------------------------
-$ gitk HEAD...FETCH_HEAD
-------------------------------------------------
-
-Isto significa "mostre tudo que é alcançável de qualquer um deles, mas
-exclua tudo que é alcançável a partir de ambos".
-
-Por favor, note que essas notações de intervalo podem ser usadas tanto
-com gitk quanto com "git log".
-
-Após inspecionar o que Bob fez, se não há nada urgente, Alice pode
-decidir continuar trabalhando sem puxar de Bob. Se a história de Bob
-tem alguma coisa que Alice precisa imediatamente, Alice pode optar por
-separar seu trabalho em progresso primeiro, fazer um "pull", e, então,
-finalmente, retomar seu trabalho em progresso em cima da história
-resultante.
-
-Quando você está trabalhando em um pequeno grupo unido, não é incomum
-interagir com o mesmo repositório várias e várias vezes. Definindo um
-repositório remoto antes de tudo, você pode fazê-lo mais facilmente:
-
-------------------------------------------------
-alice$ git remote add bob /home/bob/myrepo
-------------------------------------------------
-
-Com isso, Alice pode executar a primeira parte da operação "pull" usando
-o comando 'git-fetch' sem unificar suas mudanças com seu próprio ramo,
-usando:
-
--------------------------------------
-alice$ git fetch bob
--------------------------------------
-
-Diferente da forma longa, quando Alice obteve de Bob usando um
-repositório remoto antes definido com 'git-remote', o que foi obtido é
-armazenado em um ramo remoto, neste caso `bob/master`. Então, após isso:
-
--------------------------------------
-alice$ git log -p master..bob/master
--------------------------------------
-
-mostra uma lista de todas as mudanças que Bob fez desde que ramificou do
-ramo master de Alice.
-
-Após examinar essas mudanças, Alice pode unificá-las em seu ramo master:
-
--------------------------------------
-alice$ git merge bob/master
--------------------------------------
-
-Esse `merge` pode também ser feito puxando de seu próprio ramo remoto,
-assim:
-
--------------------------------------
-alice$ git pull . remotes/bob/master
--------------------------------------
-
-Note que 'git pull' sempre unifica ao ramo atual, independente do que
-mais foi passado na linha de comando.
-
-Depois, Bob pode atualizar seu repositório com as últimas mudanças de
-Alice, usando
-
--------------------------------------
-bob$ git pull
--------------------------------------
-
-Note que ele não precisa dar o caminho do repositório de Alice; quando
-Bob clonou seu repositório, o git armazenou a localização de seu
-repositório na configuração do mesmo, e essa localização é usada
-para puxar:
-
--------------------------------------
-bob$ git config --get remote.origin.url
-/home/alice/project
--------------------------------------
-
-(A configuração completa criada por 'git-clone' é visível usando `git
-config -l`, e a página de manual linkgit:git-config[1] explica o
-significado de cada opção.)
-
-Git também mantém uma cópia limpa do ramo master de Alice sob o nome
-"origin/master":
-
--------------------------------------
-bob$ git branch -r
- origin/master
--------------------------------------
-
-Se Bob decidir depois em trabalhar em um host diferente, ele ainda pode
-executar clones e puxar usando o protocolo ssh:
-
--------------------------------------
-bob$ git clone alice.org:/home/alice/project myrepo
--------------------------------------
-
-Alternativamente, o git tem um protocolo nativo, ou pode usar rsync ou
-http; veja linkgit:git-pull[1] para detalhes.
-
-Git pode também ser usado em um modo parecido com CVS, com um
-repositório central para o qual vários usuários empurram modificações;
-veja linkgit:git-push[1] e linkgit:gitcvs-migration[7].
-
-Explorando história
------------------
-
-A história no git é representada como uma série de commits
-interrelacionados. Nós já vimos que o comando 'git-log' pode listar
-esses commits. Note que a primeira linha de cada entrada no log também
-dá o nome para o commit:
-
--------------------------------------
-$ git log
-commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
-Author: Junio C Hamano <junkio@cox.net>
-Date: Tue May 16 17:18:22 2006 -0700
-
- merge-base: Clarify the comments on post processing.
--------------------------------------
-
-Nós podemos dar este nome ao 'git-show' para ver os detalhes sobre este
-commit.
-
--------------------------------------
-$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
--------------------------------------
-
-Mas há outras formas de se referir aos commits. Você pode usar qualquer
-parte inicial do nome que seja longo o bastante para identificar
-unicamente o commit:
-
--------------------------------------
-$ git show c82a22c39c # os primeiros caracteres do nome são o bastante
- # usualmente
-$ git show HEAD # a ponta do ramo atual
-$ git show experimental # a ponta do ramo "experimental"
--------------------------------------
-
-Todo commit normalmente tem um commit "pai" que aponta para o estado
-anterior do projeto:
-
--------------------------------------
-$ git show HEAD^ # para ver o pai de HEAD
-$ git show HEAD^^ # para ver o avô de HEAD
-$ git show HEAD~4 # para ver o trisavô de HEAD
--------------------------------------
-
-Note que commits de unificação podem ter mais de um pai:
-
--------------------------------------
-$ git show HEAD^1 # mostra o primeiro pai de HEAD (o mesmo que HEAD^)
-$ git show HEAD^2 # mostra o segundo pai de HEAD
--------------------------------------
-
-Você também pode dar aos commits nomes à sua escolha; após executar
-
--------------------------------------
-$ git tag v2.5 1b2e1d63ff
--------------------------------------
-
-você pode se referir a 1b2e1d63ff pelo nome "v2.5". Se você pretende
-compartilhar esse nome com outras pessoas (por exemplo, para identificar
-uma versão de lançamento), você deveria criar um objeto "tag", e talvez
-assiná-lo; veja linkgit:git-tag[1] para detalhes.
-
-Qualquer comando git que precise conhecer um commit pode receber
-quaisquer desses nomes. Por exemplo:
-
--------------------------------------
-$ git diff v2.5 HEAD # compara o HEAD atual com v2.5
-$ git branch stable v2.5 # inicia um novo ramo chamado "stable" baseado
- # em v2.5
-$ git reset --hard HEAD^ # reseta seu ramo atual e seu diretório de
- # trabalho a seu estado em HEAD^
--------------------------------------
-
-Seja cuidadoso com o último comando: além de perder quaisquer mudanças
-em seu diretório de trabalho, ele também remove todos os commits
-posteriores desse ramo. Se esse ramo é o único ramo contendo esses
-commits, eles serão perdidos. Também, não use 'git-reset' num ramo
-publicamente visível de onde outros desenvolvedores puxam, já que vai
-forçar unificações desnecessárias para que outros desenvolvedores limpem
-a história. Se você precisa desfazer mudanças que você empurrou, use
-'git-revert' no lugar.
-
-O comando 'git-grep' pode buscar strings em qualquer versão de seu
-projeto, então
-
--------------------------------------
-$ git grep "hello" v2.5
--------------------------------------
-
-procura por todas as ocorrências de "hello" em v2.5.
-
-Se você deixar de fora o nome do commit, 'git-grep' irá procurar
-quaisquer dos arquivos que ele gerencia no diretório corrente. Então
-
--------------------------------------
-$ git grep "hello"
--------------------------------------
-
-é uma forma rápida de buscar somente os arquivos que são rastreados pelo
-git.
-
-Muitos comandos git também recebem um conjunto de commits, o que pode
-ser especificado de várias formas. Aqui estão alguns exemplos com 'git-log':
-
--------------------------------------
-$ git log v2.5..v2.6 # commits entre v2.5 e v2.6
-$ git log v2.5.. # commits desde v2.5
-$ git log --since="2 weeks ago" # commits das últimas 2 semanas
-$ git log v2.5.. Makefile # commits desde v2.5 que modificam
- # Makefile
--------------------------------------
-
-Você também pode dar ao 'git-log' um "intervalo" de commits onde o
-primeiro não é necessariamente um ancestral do segundo; por exemplo, se
-as pontas dos ramos "stable" e "master" divergiram de um commit
-comum algum tempo atrás, então
-
--------------------------------------
-$ git log stable..master
--------------------------------------
-
-irá listar os commits feitos no ramo "master" mas não no ramo
-"stable", enquanto
-
--------------------------------------
-$ git log master..stable
--------------------------------------
-
-irá listar a lista de commits feitos no ramo "stable" mas não no ramo
-"master".
-
-O comando 'git-log' tem uma fraqueza: ele precisa mostrar os commits em
-uma lista. Quando a história tem linhas de desenvolvimento que
-divergiram e então foram unificadas novamente, a ordem em que 'git-log'
-apresenta essas mudanças é irrelevante.
-
-A maioria dos projetos com múltiplos contribuidores (como o kernel
-Linux, ou o próprio git) tem unificações frequentes, e 'gitk' faz um
-trabalho melhor de visualizar sua história. Por exemplo,
-
--------------------------------------
-$ gitk --since="2 weeks ago" drivers/
--------------------------------------
-
-permite a você navegar em quaisquer commits desde as últimas duas semanas
-de commits que modificaram arquivos sob o diretório "drivers". (Nota:
-você pode ajustar as fontes do gitk segurando a tecla control enquanto
-pressiona "-" ou "+".)
-
-Finalmente, a maioria dos comandos que recebem nomes de arquivo permitirão
-também, opcionalmente, preceder qualquer nome de arquivo por um
-commit, para especificar uma versão particular do arquivo:
-
--------------------------------------
-$ git diff v2.5:Makefile HEAD:Makefile.in
--------------------------------------
-
-Você pode usar 'git-show' para ver tal arquivo:
-
--------------------------------------
-$ git show v2.5:Makefile
--------------------------------------
-
-Próximos passos
-----------
-
-Este tutorial deve ser o bastante para operar controle de revisão
-distribuído básico para seus projetos. No entanto, para entender
-plenamente a profundidade e o poder do git você precisa entender duas
-idéias simples nas quais ele se baseia:
-
- * A base de objetos é um sistema bem elegante usado para armazenar a
- história de seu projeto--arquivos, diretórios, e commits.
-
- * O arquivo de índice é um cache do estado de uma árvore de diretório,
- usado para criar commits, restaurar diretórios de trabalho, e
- armazenar as várias árvores envolvidas em uma unificação.
-
-A parte dois deste tutorial explica a base de objetos, o arquivo de
-índice, e algumas outras coisinhas que você vai precisar pra usar o
-máximo do git. Você pode encontrá-la em linkgit:gittutorial-2[7].
-
-Se você não quiser continuar com o tutorial agora nesse momento, algumas
-outras digressões que podem ser interessantes neste ponto são:
-
- * linkgit:git-format-patch[1], linkgit:git-am[1]: Estes convertem
- séries de commits em patches para email, e vice-versa, úteis para
- projetos como o kernel Linux que dependem fortemente de patches
- enviados por email.
-
- * linkgit:git-bisect[1]: Quando há uma regressão em seu projeto, uma
- forma de rastrear um bug é procurando pela história para encontrar o
- commit culpado. Git bisect pode ajudar a executar uma busca binária
- por esse commit. Ele é inteligente o bastante para executar uma
- busca próxima da ótima mesmo no caso de uma história complexa
- não-linear com muitos ramos unificados.
-
- * link:everyday.html[GIT diariamente com 20 e tantos comandos]
-
- * linkgit:gitcvs-migration[7]: Git para usuários de CVS.
-
-VEJA TAMBÉM
---------
-linkgit:gittutorial-2[7],
-linkgit:gitcvs-migration[7],
-linkgit:gitcore-tutorial[7],
-linkgit:gitglossary[7],
-linkgit:git-help[1],
-link:everyday.html[git diariamente],
-link:user-manual.html[O Manual do Usuário git]
-
-GIT
----
-Parte da suite linkgit:git[1].
diff --git a/Makefile b/Makefile
index 4bcbd9d7cf..21eeef41ee 100644
--- a/Makefile
+++ b/Makefile
@@ -465,7 +465,7 @@ SCRIPT_PERL += git-relink.perl
SCRIPT_PERL += git-send-email.perl
SCRIPT_PERL += git-svn.perl
-SCRIPT_PYTHON += git-remote-testgit.py
+SCRIPT_PYTHON += git-remote-testpy.py
SCRIPT_PYTHON += git-p4.py
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
@@ -519,6 +519,7 @@ TEST_PROGRAMS_NEED_X += test-sigchain
TEST_PROGRAMS_NEED_X += test-string-list
TEST_PROGRAMS_NEED_X += test-subprocess
TEST_PROGRAMS_NEED_X += test-svn-fe
+TEST_PROGRAMS_NEED_X += test-wildmatch
TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
@@ -691,6 +692,7 @@ LIB_H += userdiff.h
LIB_H += utf8.h
LIB_H += varint.h
LIB_H += walker.h
+LIB_H += wildmatch.h
LIB_H += wt-status.h
LIB_H += xdiff-interface.h
LIB_H += xdiff/xdiff.h
@@ -825,6 +827,7 @@ LIB_OBJS += utf8.o
LIB_OBJS += varint.o
LIB_OBJS += version.o
LIB_OBJS += walker.o
+LIB_OBJS += wildmatch.o
LIB_OBJS += wrapper.o
LIB_OBJS += write_or_die.o
LIB_OBJS += ws.o
@@ -1680,7 +1683,7 @@ endef
GIT-SCRIPT-DEFINES: FORCE
@FLAGS='$(SCRIPT_DEFINES)'; \
if test x"$$FLAGS" != x"`cat $@ 2>/dev/null`" ; then \
- echo 1>&2 " * new script parameters"; \
+ echo >&2 " * new script parameters"; \
echo "$$FLAGS" >$@; \
fi
@@ -1742,7 +1745,7 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
endif # NO_PERL
ifndef NO_PYTHON
-$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS GIT-PREFIX
+$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS GIT-PREFIX GIT-PYTHON-VARS
$(patsubst %.py,%,$(SCRIPT_PYTHON)): % : %.py
$(QUIET_GEN)$(RM) $@ $@+ && \
INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C git_remote_helpers -s \
@@ -1772,8 +1775,14 @@ configure: configure.ac GIT-VERSION-FILE
$(RM) $<+
ifdef AUTOCONFIGURED
-config.status: configure
- $(QUIET_GEN)if test -f config.status; then \
+# We avoid depending on 'configure' here, because it gets rebuilt
+# every time GIT-VERSION-FILE is modified, only to update the embedded
+# version number string, which config.status does not care about. We
+# do want to recheck when the platform/environment detection logic
+# changes, hence this depends on configure.ac.
+config.status: configure.ac
+ $(QUIET_GEN)$(MAKE) configure && \
+ if test -f config.status; then \
./config.status --recheck; \
else \
./configure; \
@@ -2061,7 +2070,7 @@ TRACK_PREFIX = $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
GIT-PREFIX: FORCE
@FLAGS='$(TRACK_PREFIX)'; \
if test x"$$FLAGS" != x"`cat GIT-PREFIX 2>/dev/null`" ; then \
- echo 1>&2 " * new prefix flags"; \
+ echo >&2 " * new prefix flags"; \
echo "$$FLAGS" >GIT-PREFIX; \
fi
@@ -2070,7 +2079,7 @@ TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS)):$(USE_GETTEXT_SCHEME)
GIT-CFLAGS: FORCE
@FLAGS='$(TRACK_CFLAGS)'; \
if test x"$$FLAGS" != x"`cat GIT-CFLAGS 2>/dev/null`" ; then \
- echo 1>&2 " * new build flags"; \
+ echo >&2 " * new build flags"; \
echo "$$FLAGS" >GIT-CFLAGS; \
fi
@@ -2079,7 +2088,7 @@ TRACK_LDFLAGS = $(subst ','\'',$(ALL_LDFLAGS))
GIT-LDFLAGS: FORCE
@FLAGS='$(TRACK_LDFLAGS)'; \
if test x"$$FLAGS" != x"`cat GIT-LDFLAGS 2>/dev/null`" ; then \
- echo 1>&2 " * new link flags"; \
+ echo >&2 " * new link flags"; \
echo "$$FLAGS" >GIT-LDFLAGS; \
fi
@@ -2121,14 +2130,14 @@ ifdef GIT_PERF_MAKE_OPTS
@echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@
endif
-### Detect Tck/Tk interpreter path changes
-ifndef NO_TCLTK
-TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)')
+### Detect Python interpreter path changes
+ifndef NO_PYTHON
+TRACK_PYTHON = $(subst ','\'',-DPYTHON_PATH='$(PYTHON_PATH_SQ)')
-GIT-GUI-VARS: FORCE
- @VARS='$(TRACK_VARS)'; \
+GIT-PYTHON-VARS: FORCE
+ @VARS='$(TRACK_PYTHON)'; \
if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
- echo 1>&2 " * new Tcl/Tk interpreter location"; \
+ echo >&2 " * new Python interpreter location"; \
echo "$$VARS" >$@; \
fi
endif
@@ -2407,8 +2416,8 @@ ifndef NO_TCLTK
$(MAKE) -C gitk-git clean
$(MAKE) -C git-gui clean
endif
- $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS
- $(RM) GIT-USER-AGENT GIT-PREFIX GIT-SCRIPT-DEFINES
+ $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-BUILD-OPTIONS
+ $(RM) GIT-USER-AGENT GIT-PREFIX GIT-SCRIPT-DEFINES GIT-PYTHON-VARS
.PHONY: all install profile-clean clean strip
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
diff --git a/advice.c b/advice.c
index edfbd4a6fb..d287927280 100644
--- a/advice.c
+++ b/advice.c
@@ -1,9 +1,10 @@
#include "cache.h"
-int advice_push_nonfastforward = 1;
+int advice_push_update_rejected = 1;
int advice_push_non_ff_current = 1;
int advice_push_non_ff_default = 1;
int advice_push_non_ff_matching = 1;
+int advice_push_already_exists = 1;
int advice_status_hints = 1;
int advice_commit_before_merge = 1;
int advice_resolve_conflict = 1;
@@ -14,15 +15,19 @@ static struct {
const char *name;
int *preference;
} advice_config[] = {
- { "pushnonfastforward", &advice_push_nonfastforward },
+ { "pushupdaterejected", &advice_push_update_rejected },
{ "pushnonffcurrent", &advice_push_non_ff_current },
{ "pushnonffdefault", &advice_push_non_ff_default },
{ "pushnonffmatching", &advice_push_non_ff_matching },
+ { "pushalreadyexists", &advice_push_already_exists },
{ "statushints", &advice_status_hints },
{ "commitbeforemerge", &advice_commit_before_merge },
{ "resolveconflict", &advice_resolve_conflict },
{ "implicitidentity", &advice_implicit_identity },
{ "detachedhead", &advice_detached_head },
+
+ /* make this an alias for backward compatibility */
+ { "pushnonfastforward", &advice_push_update_rejected }
};
void advise(const char *advice, ...)
diff --git a/advice.h b/advice.h
index f3cdbbf29e..8bf63563a5 100644
--- a/advice.h
+++ b/advice.h
@@ -3,10 +3,11 @@
#include "git-compat-util.h"
-extern int advice_push_nonfastforward;
+extern int advice_push_update_rejected;
extern int advice_push_non_ff_current;
extern int advice_push_non_ff_default;
extern int advice_push_non_ff_matching;
+extern int advice_push_already_exists;
extern int advice_status_hints;
extern int advice_commit_before_merge;
extern int advice_resolve_conflict;
diff --git a/archive.c b/archive.c
index 466640479e..93e00bb4ae 100644
--- a/archive.c
+++ b/archive.c
@@ -120,6 +120,8 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
strbuf_add(&path, args->base, args->baselen);
strbuf_add(&path, base, baselen);
strbuf_addstr(&path, filename);
+ if (S_ISDIR(mode) || S_ISGITLINK(mode))
+ strbuf_addch(&path, '/');
path_without_prefix = path.buf + args->baselen;
setup_archive_check(check);
@@ -130,7 +132,6 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
}
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
- strbuf_addch(&path, '/');
if (args->verbose)
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
err = write_entry(args, sha1, path.buf, path.len, mode);
diff --git a/attr.c b/attr.c
index 097ae87f3c..466c93fa50 100644
--- a/attr.c
+++ b/attr.c
@@ -564,17 +564,24 @@ static void bootstrap_attr_stack(void)
attr_stack = elem;
}
+static const char *find_basename(const char *path)
+{
+ const char *cp, *last_slash = NULL;
+
+ for (cp = path; *cp; cp++) {
+ if (*cp == '/' && cp[1])
+ last_slash = cp;
+ }
+ return last_slash ? last_slash + 1 : path;
+}
+
static void prepare_attr_stack(const char *path)
{
struct attr_stack *elem, *info;
int dirlen, len;
const char *cp;
- cp = strrchr(path, '/');
- if (!cp)
- dirlen = 0;
- else
- dirlen = cp - path;
+ dirlen = find_basename(path) - path;
/*
* At the bottom of the attribute stack is the built-in
@@ -668,6 +675,10 @@ static int path_matches(const char *pathname, int pathlen,
const char *pattern = pat->pattern;
int prefix = pat->nowildcardlen;
+ if ((pat->flags & EXC_FLAG_MUSTBEDIR) &&
+ ((!pathlen) || (pathname[pathlen-1] != '/')))
+ return 0;
+
if (pat->flags & EXC_FLAG_NODIR) {
return match_basename(basename,
pathlen - (basename - pathname),
@@ -758,9 +769,7 @@ static void collect_all_attrs(const char *path)
for (i = 0; i < attr_nr; i++)
check_all_attr[i].value = ATTR__UNKNOWN;
- basename = strrchr(path, '/');
- basename = basename ? basename + 1 : path;
-
+ basename = find_basename(path);
pathlen = strlen(path);
rem = attr_nr;
for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
diff --git a/builtin.h b/builtin.h
index 3faf9d6691..7e7bbd665a 100644
--- a/builtin.h
+++ b/builtin.h
@@ -15,7 +15,8 @@ extern const char git_more_info_string[];
extern void prune_packed_objects(int);
struct fmt_merge_msg_opts {
- unsigned add_title:1;
+ unsigned add_title:1,
+ credit_people:1;
int shortlog_len;
};
diff --git a/builtin/apply.c b/builtin/apply.c
index 156b3ce3b7..6c11e8bc73 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -2095,7 +2095,7 @@ static void update_pre_post_images(struct image *preimage,
char *buf,
size_t len, size_t postlen)
{
- int i, ctx;
+ int i, ctx, reduced;
char *new, *old, *fixed;
struct image fixed_preimage;
@@ -2105,8 +2105,10 @@ static void update_pre_post_images(struct image *preimage,
* free "oldlines".
*/
prepare_image(&fixed_preimage, buf, len, 1);
- assert(fixed_preimage.nr == preimage->nr);
- for (i = 0; i < preimage->nr; i++)
+ assert(postlen
+ ? fixed_preimage.nr == preimage->nr
+ : fixed_preimage.nr <= preimage->nr);
+ for (i = 0; i < fixed_preimage.nr; i++)
fixed_preimage.line[i].flag = preimage->line[i].flag;
free(preimage->line_allocated);
*preimage = fixed_preimage;
@@ -2126,7 +2128,8 @@ static void update_pre_post_images(struct image *preimage,
else
new = old;
fixed = preimage->buf;
- for (i = ctx = 0; i < postimage->nr; i++) {
+
+ for (i = reduced = ctx = 0; i < postimage->nr; i++) {
size_t len = postimage->line[i].len;
if (!(postimage->line[i].flag & LINE_COMMON)) {
/* an added line -- no counterparts in preimage */
@@ -2145,8 +2148,15 @@ static void update_pre_post_images(struct image *preimage,
fixed += preimage->line[ctx].len;
ctx++;
}
- if (preimage->nr <= ctx)
- die(_("oops"));
+
+ /*
+ * preimage is expected to run out, if the caller
+ * fixed addition of trailing blank lines.
+ */
+ if (preimage->nr <= ctx) {
+ reduced++;
+ continue;
+ }
/* and copy it in, while fixing the line length */
len = preimage->line[ctx].len;
@@ -2159,6 +2169,7 @@ static void update_pre_post_images(struct image *preimage,
/* Fix the length of the whole thing */
postimage->len = new - postimage->buf;
+ postimage->nr -= reduced;
}
static int match_fragment(struct image *img,
diff --git a/builtin/branch.c b/builtin/branch.c
index 1ec9c02612..873f624d1c 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -725,7 +725,7 @@ static int edit_branch_description(const char *branch_name)
stripspace(&buf, 1);
strbuf_addf(&name, "branch.%s.description", branch_name);
- status = git_config_set(name.buf, buf.buf);
+ status = git_config_set(name.buf, buf.len ? buf.buf : NULL);
strbuf_release(&name);
strbuf_release(&buf);
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 12220ad8da..77dffd1ce3 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -474,18 +474,21 @@ static void handle_tag(const char *name, struct tag *tag)
(int)message_size, (int)message_size, message ? message : "");
}
-static void get_tags_and_duplicates(struct object_array *pending,
+static void get_tags_and_duplicates(struct rev_cmdline_info *info,
struct string_list *extra_refs)
{
struct tag *tag;
int i;
- for (i = 0; i < pending->nr; i++) {
- struct object_array_entry *e = pending->objects + i;
+ for (i = 0; i < info->nr; i++) {
+ struct rev_cmdline_entry *e = info->rev + i;
unsigned char sha1[20];
- struct commit *commit = commit;
+ struct commit *commit;
char *full_name;
+ if (e->flags & UNINTERESTING)
+ continue;
+
if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)
continue;
@@ -523,10 +526,14 @@ static void get_tags_and_duplicates(struct object_array *pending,
typename(e->item->type));
continue;
}
- if (commit->util)
- /* more than one name for the same object */
+
+ /*
+ * This ref will not be updated through a commit, lets make
+ * sure it gets properly updated eventually.
+ */
+ if (commit->util || commit->object.flags & SHOWN)
string_list_append(extra_refs, full_name)->util = commit;
- else
+ if (!commit->util)
commit->util = full_name;
}
}
@@ -614,6 +621,10 @@ static void import_marks(char *input_file)
if (object->flags & SHOWN)
error("Object %s already has a mark", sha1_to_hex(sha1));
+ if (object->type != OBJ_COMMIT)
+ /* only commits */
+ continue;
+
mark_object(object, mark);
if (last_idnum < mark)
last_idnum = mark;
@@ -677,7 +688,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
if (import_filename && revs.prune_data.nr)
full_tree = 1;
- get_tags_and_duplicates(&revs.pending, &extra_refs);
+ get_tags_and_duplicates(&revs.cmdline, &extra_refs);
if (prepare_revision_walk(&revs))
die("revision walk setup failed");
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index e2e27b2c40..d9af43c257 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -232,8 +232,9 @@ static void record_person(int which, struct string_list *people,
{
char *name_buf, *name, *name_end;
struct string_list_item *elem;
- const char *field = (which == 'a') ? "\nauthor " : "\ncommitter ";
+ const char *field;
+ field = (which == 'a') ? "\nauthor " : "\ncommitter ";
name = strstr(commit->buffer, field);
if (!name)
return;
@@ -323,7 +324,8 @@ static void add_people_info(struct strbuf *out,
static void shortlog(const char *name,
struct origin_data *origin_data,
struct commit *head,
- struct rev_info *rev, int limit,
+ struct rev_info *rev,
+ struct fmt_merge_msg_opts *opts,
struct strbuf *out)
{
int i, count = 0;
@@ -335,6 +337,7 @@ static void shortlog(const char *name,
int flags = UNINTERESTING | TREESAME | SEEN | SHOWN | ADDED;
struct strbuf sb = STRBUF_INIT;
const unsigned char *sha1 = origin_data->sha1;
+ int limit = opts->shortlog_len;
branch = deref_tag(parse_object(sha1), sha1_to_hex(sha1), 40);
if (!branch || branch->type != OBJ_COMMIT)
@@ -351,13 +354,15 @@ static void shortlog(const char *name,
if (commit->parents && commit->parents->next) {
/* do not list a merge but count committer */
- record_person('c', &committers, commit);
+ if (opts->credit_people)
+ record_person('c', &committers, commit);
continue;
}
- if (!count)
+ if (!count && opts->credit_people)
/* the 'tip' committer */
record_person('c', &committers, commit);
- record_person('a', &authors, commit);
+ if (opts->credit_people)
+ record_person('a', &authors, commit);
count++;
if (subjects.nr > limit)
continue;
@@ -372,7 +377,8 @@ static void shortlog(const char *name,
string_list_append(&subjects, strbuf_detach(&sb, NULL));
}
- add_people_info(out, &authors, &committers);
+ if (opts->credit_people)
+ add_people_info(out, &authors, &committers);
if (count > limit)
strbuf_addf(out, "\n* %s: (%d commits)\n", name, count);
else
@@ -635,7 +641,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
for (i = 0; i < origins.nr; i++)
shortlog(origins.items[i].string,
origins.items[i].util,
- head, &rev, opts->shortlog_len, out);
+ head, &rev, opts, out);
}
strbuf_complete_line(out);
@@ -690,6 +696,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
memset(&opts, 0, sizeof(opts));
opts.add_title = !message;
+ opts.credit_people = 1;
opts.shortlog_len = shortlog_len;
ret = fmt_merge_msg(&input, &output, &opts);
diff --git a/builtin/log.c b/builtin/log.c
index e7b7db1cac..3899b1d43a 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1016,8 +1016,9 @@ static char *find_branch_name(struct rev_info *rev)
{
int i, positive = -1;
unsigned char branch_sha1[20];
- struct strbuf buf = STRBUF_INIT;
- const char *branch;
+ const unsigned char *tip_sha1;
+ const char *ref;
+ char *full_ref, *branch = NULL;
for (i = 0; i < rev->cmdline.nr; i++) {
if (rev->cmdline.rev[i].flags & UNINTERESTING)
@@ -1027,18 +1028,27 @@ static char *find_branch_name(struct rev_info *rev)
else
return NULL;
}
- if (positive < 0)
+ if (0 <= positive) {
+ ref = rev->cmdline.rev[positive].name;
+ tip_sha1 = rev->cmdline.rev[positive].item->sha1;
+ } else if (!rev->cmdline.nr && rev->pending.nr == 1 &&
+ !strcmp(rev->pending.objects[0].name, "HEAD")) {
+ /*
+ * No actual ref from command line, but "HEAD" from
+ * rev->def was added in setup_revisions()
+ * e.g. format-patch --cover-letter -12
+ */
+ ref = "HEAD";
+ tip_sha1 = rev->pending.objects[0].item->sha1;
+ } else {
return NULL;
- strbuf_addf(&buf, "refs/heads/%s", rev->cmdline.rev[positive].name);
- branch = resolve_ref_unsafe(buf.buf, branch_sha1, 1, NULL);
- if (!branch ||
- prefixcmp(branch, "refs/heads/") ||
- hashcmp(rev->cmdline.rev[positive].item->sha1, branch_sha1))
- branch = NULL;
- strbuf_release(&buf);
- if (branch)
- return xstrdup(rev->cmdline.rev[positive].name);
- return NULL;
+ }
+ if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) &&
+ !prefixcmp(full_ref, "refs/heads/") &&
+ !hashcmp(tip_sha1, branch_sha1))
+ branch = xstrdup(full_ref + strlen("refs/heads/"));
+ free(full_ref);
+ return branch;
}
int cmd_format_patch(int argc, const char **argv, const char *prefix)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index b5434af0c8..4a9ee690c7 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -337,7 +337,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
matchbuf[0] = prefix;
matchbuf[1] = NULL;
init_pathspec(&pathspec, matchbuf);
- pathspec.items[0].use_wildcard = 0;
+ pathspec.items[0].nowildcard_len = pathspec.items[0].len;
} else
init_pathspec(&pathspec, NULL);
if (read_tree(tree, 1, &pathspec))
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 235c17cc01..fb76e38d84 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -168,7 +168,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
init_pathspec(&pathspec, get_pathspec(prefix, argv + 1));
for (i = 0; i < pathspec.nr; i++)
- pathspec.items[i].use_wildcard = 0;
+ pathspec.items[i].nowildcard_len = pathspec.items[i].len;
pathspec.has_wildcard = 0;
tree = parse_tree_indirect(sha1);
if (!tree)
diff --git a/builtin/merge.c b/builtin/merge.c
index a96e8eac19..9307e9c726 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -800,8 +800,9 @@ static void prepare_to_commit(struct commit_list *remoteheads)
if (0 < option_edit)
strbuf_add_lines(&msg, "# ", comment, strlen(comment));
write_merge_msg(&msg);
- run_hook(get_index_file(), "prepare-commit-msg",
- git_path("MERGE_MSG"), "merge", NULL, NULL);
+ if (run_hook(get_index_file(), "prepare-commit-msg",
+ git_path("MERGE_MSG"), "merge", NULL, NULL))
+ abort_commit(remoteheads, NULL);
if (0 < option_edit) {
if (launch_editor(git_path("MERGE_MSG"), NULL, NULL))
abort_commit(remoteheads, NULL);
@@ -1221,6 +1222,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
memset(&opts, 0, sizeof(opts));
opts.add_title = !have_message;
opts.shortlog_len = shortlog_len;
+ opts.credit_people = (0 < option_edit);
fmt_merge_msg(&merge_names, &merge_msg, &opts);
if (merge_msg.len)
diff --git a/builtin/push.c b/builtin/push.c
index db9ba30b08..8491e431e4 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -220,31 +220,42 @@ static const char message_advice_checkout_pull_push[] =
"(e.g. 'git pull') before pushing again.\n"
"See the 'Note about fast-forwards' in 'git push --help' for details.");
+static const char message_advice_ref_already_exists[] =
+ N_("Updates were rejected because the destination reference already exists\n"
+ "in the remote.");
+
static void advise_pull_before_push(void)
{
- if (!advice_push_non_ff_current || !advice_push_nonfastforward)
+ if (!advice_push_non_ff_current || !advice_push_update_rejected)
return;
advise(_(message_advice_pull_before_push));
}
static void advise_use_upstream(void)
{
- if (!advice_push_non_ff_default || !advice_push_nonfastforward)
+ if (!advice_push_non_ff_default || !advice_push_update_rejected)
return;
advise(_(message_advice_use_upstream));
}
static void advise_checkout_pull_push(void)
{
- if (!advice_push_non_ff_matching || !advice_push_nonfastforward)
+ if (!advice_push_non_ff_matching || !advice_push_update_rejected)
return;
advise(_(message_advice_checkout_pull_push));
}
+static void advise_ref_already_exists(void)
+{
+ if (!advice_push_already_exists || !advice_push_update_rejected)
+ return;
+ advise(_(message_advice_ref_already_exists));
+}
+
static int push_with_options(struct transport *transport, int flags)
{
int err;
- int nonfastforward;
+ unsigned int reject_reasons;
transport_set_verbosity(transport, verbosity, progress);
@@ -257,7 +268,7 @@ static int push_with_options(struct transport *transport, int flags)
if (verbosity > 0)
fprintf(stderr, _("Pushing to %s\n"), transport->url);
err = transport_push(transport, refspec_nr, refspec, flags,
- &nonfastforward);
+ &reject_reasons);
if (err != 0)
error(_("failed to push some refs to '%s'"), transport->url);
@@ -265,18 +276,15 @@ static int push_with_options(struct transport *transport, int flags)
if (!err)
return 0;
- switch (nonfastforward) {
- default:
- break;
- case NON_FF_HEAD:
+ if (reject_reasons & REJECT_NON_FF_HEAD) {
advise_pull_before_push();
- break;
- case NON_FF_OTHER:
+ } else if (reject_reasons & REJECT_NON_FF_OTHER) {
if (default_matching_used)
advise_use_upstream();
else
advise_checkout_pull_push();
- break;
+ } else if (reject_reasons & REJECT_ALREADY_EXISTS) {
+ advise_ref_already_exists();
}
return 1;
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index d34201372d..f849e0a4a0 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -44,6 +44,11 @@ static void print_helper_status(struct ref *ref)
msg = "non-fast forward";
break;
+ case REF_STATUS_REJECT_ALREADY_EXISTS:
+ res = "error";
+ msg = "already exists";
+ break;
+
case REF_STATUS_REJECT_NODELETE:
case REF_STATUS_REMOTE_REJECT:
res = "error";
@@ -85,7 +90,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
int send_all = 0;
const char *receivepack = "git-receive-pack";
int flags;
- int nonfastforward = 0;
+ unsigned int reject_reasons;
int progress = -1;
argv++;
@@ -223,7 +228,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
ret |= finish_connect(conn);
if (!helper_status)
- transport_print_push_status(dest, remote_refs, args.verbose, 0, &nonfastforward);
+ transport_print_push_status(dest, remote_refs, args.verbose, 0, &reject_reasons);
if (!args.dry_run && remote) {
struct ref *ref;
diff --git a/cache.h b/cache.h
index 2b192d24ac..c257953fa7 100644
--- a/cache.h
+++ b/cache.h
@@ -362,6 +362,7 @@ static inline enum object_type object_type(unsigned int mode)
#define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
#define GIT_NOTES_REWRITE_REF_ENVIRONMENT "GIT_NOTES_REWRITE_REF"
#define GIT_NOTES_REWRITE_MODE_ENVIRONMENT "GIT_NOTES_REWRITE_MODE"
+#define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS"
/*
* Repository-local GIT_* environment variables
@@ -473,6 +474,8 @@ extern int index_name_is_other(const struct index_state *, const char *, int);
extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
+#define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */
+
struct pathspec {
const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
int nr;
@@ -482,7 +485,8 @@ struct pathspec {
struct pathspec_item {
const char *match;
int len;
- unsigned int use_wildcard:1;
+ int nowildcard_len;
+ int flags;
} *items;
};
@@ -490,6 +494,8 @@ extern int init_pathspec(struct pathspec *, const char **);
extern void free_pathspec(struct pathspec *);
extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
+extern int limit_pathspec_to_literal(void);
+
#define HASH_WRITE_OBJECT 1
#define HASH_FORMAT_CHECK 2
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
@@ -1000,14 +1006,19 @@ struct ref {
unsigned char old_sha1[20];
unsigned char new_sha1[20];
char *symref;
- unsigned int force:1,
+ unsigned int
+ force:1,
+ requires_force:1,
merge:1,
nonfastforward:1,
+ not_forwardable:1,
+ update:1,
deletion:1;
enum {
REF_STATUS_NONE = 0,
REF_STATUS_OK,
REF_STATUS_REJECT_NONFASTFORWARD,
+ REF_STATUS_REJECT_ALREADY_EXISTS,
REF_STATUS_REJECT_NODELETE,
REF_STATUS_UPTODATE,
REF_STATUS_REMOTE_REJECT,
@@ -1137,6 +1148,9 @@ extern int check_repository_format_version(const char *var, const char *value, v
extern int git_env_bool(const char *, int);
extern int git_config_system(void);
extern int config_error_nonbool(const char *);
+#ifdef __GNUC__
+#define config_error_nonbool(s) (config_error_nonbool(s), -1)
+#endif
extern const char *get_log_output_encoding(void);
extern const char *get_commit_output_encoding(void);
@@ -1156,6 +1170,7 @@ extern int author_ident_sufficiently_given(void);
extern const char *git_commit_encoding;
extern const char *git_log_output_encoding;
extern const char *git_mailmap_file;
+extern const char *git_mailmap_blob;
/* IO helper functions */
extern void maybe_flush_or_die(FILE *, const char *);
diff --git a/commit.h b/commit.h
index b6ad8f3f30..0f469e507d 100644
--- a/commit.h
+++ b/commit.h
@@ -89,6 +89,7 @@ struct pretty_print_context {
char *notes_message;
struct reflog_walk_info *reflog_info;
const char *output_encoding;
+ int color;
};
struct userformat_want {
diff --git a/compat/fnmatch/fnmatch.c b/compat/fnmatch/fnmatch.c
index b8b7dc2543..5ef0685135 100644
--- a/compat/fnmatch/fnmatch.c
+++ b/compat/fnmatch/fnmatch.c
@@ -55,7 +55,8 @@
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
-#if defined _LIBC || !defined __GNU_LIBRARY__
+#if defined NO_FNMATCH || defined NO_FNMATCH_CASEFOLD || \
+ defined _LIBC || !defined __GNU_LIBRARY__
# if defined STDC_HEADERS || !defined isascii
diff --git a/config.c b/config.c
index fb3f8681ee..7b444b68ab 100644
--- a/config.c
+++ b/config.c
@@ -58,7 +58,7 @@ static int handle_path_include(const char *path, struct config_include_data *inc
path = buf.buf;
}
- if (!access_or_warn(path, R_OK)) {
+ if (!access_or_die(path, R_OK)) {
if (++inc->depth > MAX_INCLUDE_DEPTH)
die(include_depth_advice, MAX_INCLUDE_DEPTH, path,
cf && cf->name ? cf->name : "the command line");
@@ -839,6 +839,8 @@ static int git_default_mailmap_config(const char *var, const char *value)
{
if (!strcmp(var, "mailmap.file"))
return git_config_string(&git_mailmap_file, var, value);
+ if (!strcmp(var, "mailmap.blob"))
+ return git_config_string(&git_mailmap_blob, var, value);
/* Add other config variables here and to Documentation/config.txt. */
return 0;
@@ -938,23 +940,23 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
home_config_paths(&user_config, &xdg_config, "config");
- if (git_config_system() && !access_or_warn(git_etc_gitconfig(), R_OK)) {
+ if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK)) {
ret += git_config_from_file(fn, git_etc_gitconfig(),
data);
found += 1;
}
- if (xdg_config && !access_or_warn(xdg_config, R_OK)) {
+ if (xdg_config && !access_or_die(xdg_config, R_OK)) {
ret += git_config_from_file(fn, xdg_config, data);
found += 1;
}
- if (user_config && !access_or_warn(user_config, R_OK)) {
+ if (user_config && !access_or_die(user_config, R_OK)) {
ret += git_config_from_file(fn, user_config, data);
found += 1;
}
- if (repo_config && !access_or_warn(repo_config, R_OK)) {
+ if (repo_config && !access_or_die(repo_config, R_OK)) {
ret += git_config_from_file(fn, repo_config, data);
found += 1;
}
@@ -1660,6 +1662,7 @@ int git_config_rename_section(const char *old_name, const char *new_name)
* Call this to report error for your variable that should not
* get a boolean value (i.e. "[my] var" means "true").
*/
+#undef config_error_nonbool
int config_error_nonbool(const char *var)
{
return error("Missing value for '%s'", var);
diff --git a/contrib/ciabot/ciabot.py b/contrib/ciabot/ciabot.py
index bd24395d4c..36b5665ff8 100755
--- a/contrib/ciabot/ciabot.py
+++ b/contrib/ciabot/ciabot.py
@@ -47,7 +47,13 @@
# we default to that.
#
-import os, sys, commands, socket, urllib
+import sys
+if sys.hexversion < 0x02000000:
+ # The limiter is the xml.sax module
+ sys.stderr.write("ciabot.py: requires Python 2.0.0 or later.\n")
+ sys.exit(1)
+
+import os, commands, socket, urllib
from xml.sax.saxutils import escape
# Changeset URL prefix for your repo: when the commit ID is appended
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 0b77eb1fa4..a4c48e179e 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -971,6 +971,13 @@ _git_commit ()
{
__git_has_doubledash && return
+ case "$prev" in
+ -c|-C)
+ __gitcomp_nl "$(__git_refs)" "" "${cur}"
+ return
+ ;;
+ esac
+
case "$cur" in
--cleanup=*)
__gitcomp "default strip verbatim whitespace
diff --git a/contrib/fast-import/import-zips.py b/contrib/fast-import/import-zips.py
index 82f5ed3ddc..5cec9b0129 100755
--- a/contrib/fast-import/import-zips.py
+++ b/contrib/fast-import/import-zips.py
@@ -9,10 +9,15 @@
## git log --stat import-zips
from os import popen, path
-from sys import argv, exit
+from sys import argv, exit, hexversion, stderr
from time import mktime
from zipfile import ZipFile
+if hexversion < 0x01060000:
+ # The limiter is the zipfile module
+ sys.stderr.write("import-zips.py: requires Python 1.6.0 or later.\n")
+ sys.exit(1)
+
if len(argv) < 2:
print 'Usage:', argv[0], '<zipfile>...'
exit(1)
diff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py
index 046cb2b268..232625a7b7 100755
--- a/contrib/hg-to-git/hg-to-git.py
+++ b/contrib/hg-to-git/hg-to-git.py
@@ -23,6 +23,11 @@ import os, os.path, sys
import tempfile, pickle, getopt
import re
+if sys.hexversion < 0x02030000:
+ # The behavior of the pickle module changed significantly in 2.3
+ sys.stderr.write("hg-to-git.py: requires Python 2.3 or later.\n")
+ sys.exit(1)
+
# Maps hg version -> git version
hgvers = {}
# List of children for each hg revision
diff --git a/contrib/p4import/git-p4import.py b/contrib/p4import/git-p4import.py
index b6e534b65b..593d6a0682 100644
--- a/contrib/p4import/git-p4import.py
+++ b/contrib/p4import/git-p4import.py
@@ -14,6 +14,11 @@ import sys
import time
import getopt
+if sys.hexversion < 0x02020000:
+ # The behavior of the marshal module changed significantly in 2.2
+ sys.stderr.write("git-p4import.py: requires Python 2.2 or later.\n")
+ sys.exit(1)
+
from signal import signal, \
SIGPIPE, SIGINT, SIG_DFL, \
default_int_handler
diff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr
new file mode 100755
index 0000000000..c5822e4ac9
--- /dev/null
+++ b/contrib/remote-helpers/git-remote-bzr
@@ -0,0 +1,725 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+#
+# Just copy to your ~/bin, or anywhere in your $PATH.
+# Then you can clone with:
+# % git clone bzr::/path/to/bzr/repo/or/url
+#
+# For example:
+# % git clone bzr::$HOME/myrepo
+# or
+# % git clone bzr::lp:myrepo
+#
+
+import sys
+
+import bzrlib
+if hasattr(bzrlib, "initialize"):
+ bzrlib.initialize()
+
+import bzrlib.plugin
+bzrlib.plugin.load_plugins()
+
+import bzrlib.generate_ids
+import bzrlib.transport
+
+import sys
+import os
+import json
+import re
+import StringIO
+
+NAME_RE = re.compile('^([^<>]+)')
+AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]*)>$')
+RAW_AUTHOR_RE = re.compile('^(\w+) (.+)? <(.*)> (\d+) ([+-]\d+)')
+
+def die(msg, *args):
+ sys.stderr.write('ERROR: %s\n' % (msg % args))
+ sys.exit(1)
+
+def warn(msg, *args):
+ sys.stderr.write('WARNING: %s\n' % (msg % args))
+
+def gittz(tz):
+ return '%+03d%02d' % (tz / 3600, tz % 3600 / 60)
+
+class Marks:
+
+ def __init__(self, path):
+ self.path = path
+ self.tips = {}
+ self.marks = {}
+ self.rev_marks = {}
+ self.last_mark = 0
+ self.load()
+
+ def load(self):
+ if not os.path.exists(self.path):
+ return
+
+ tmp = json.load(open(self.path))
+ self.tips = tmp['tips']
+ self.marks = tmp['marks']
+ self.last_mark = tmp['last-mark']
+
+ for rev, mark in self.marks.iteritems():
+ self.rev_marks[mark] = rev
+
+ def dict(self):
+ return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
+
+ def store(self):
+ json.dump(self.dict(), open(self.path, 'w'))
+
+ def __str__(self):
+ return str(self.dict())
+
+ def from_rev(self, rev):
+ return self.marks[rev]
+
+ def to_rev(self, mark):
+ return self.rev_marks[mark]
+
+ def next_mark(self):
+ self.last_mark += 1
+ return self.last_mark
+
+ def get_mark(self, rev):
+ self.last_mark += 1
+ self.marks[rev] = self.last_mark
+ return self.last_mark
+
+ def is_marked(self, rev):
+ return self.marks.has_key(rev)
+
+ def new_mark(self, rev, mark):
+ self.marks[rev] = mark
+ self.rev_marks[mark] = rev
+ self.last_mark = mark
+
+ def get_tip(self, branch):
+ return self.tips.get(branch, None)
+
+ def set_tip(self, branch, tip):
+ self.tips[branch] = tip
+
+class Parser:
+
+ def __init__(self, repo):
+ self.repo = repo
+ self.line = self.get_line()
+
+ def get_line(self):
+ return sys.stdin.readline().strip()
+
+ def __getitem__(self, i):
+ return self.line.split()[i]
+
+ def check(self, word):
+ return self.line.startswith(word)
+
+ def each_block(self, separator):
+ while self.line != separator:
+ yield self.line
+ self.line = self.get_line()
+
+ def __iter__(self):
+ return self.each_block('')
+
+ def next(self):
+ self.line = self.get_line()
+ if self.line == 'done':
+ self.line = None
+
+ def get_mark(self):
+ i = self.line.index(':') + 1
+ return int(self.line[i:])
+
+ def get_data(self):
+ if not self.check('data'):
+ return None
+ i = self.line.index(' ') + 1
+ size = int(self.line[i:])
+ return sys.stdin.read(size)
+
+ def get_author(self):
+ m = RAW_AUTHOR_RE.match(self.line)
+ if not m:
+ return None
+ _, name, email, date, tz = m.groups()
+ committer = '%s <%s>' % (name, email)
+ tz = int(tz)
+ tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
+ return (committer, int(date), tz)
+
+def rev_to_mark(rev):
+ global marks
+ return marks.from_rev(rev)
+
+def mark_to_rev(mark):
+ global marks
+ return marks.to_rev(mark)
+
+def fixup_user(user):
+ name = mail = None
+ user = user.replace('"', '')
+ m = AUTHOR_RE.match(user)
+ if m:
+ name = m.group(1)
+ mail = m.group(2).strip()
+ else:
+ m = NAME_RE.match(user)
+ if m:
+ name = m.group(1).strip()
+
+ return '%s <%s>' % (name, mail)
+
+def get_filechanges(cur, prev):
+ modified = {}
+ removed = {}
+
+ changes = cur.changes_from(prev)
+
+ for path, fid, kind in changes.added:
+ modified[path] = fid
+ for path, fid, kind in changes.removed:
+ removed[path] = None
+ for path, fid, kind, mod, _ in changes.modified:
+ modified[path] = fid
+ for oldpath, newpath, fid, kind, mod, _ in changes.renamed:
+ removed[oldpath] = None
+ modified[newpath] = fid
+
+ return modified, removed
+
+def export_files(tree, files):
+ global marks, filenodes
+
+ final = []
+ for path, fid in files.iteritems():
+ kind = tree.kind(fid)
+
+ h = tree.get_file_sha1(fid)
+
+ if kind == 'symlink':
+ d = tree.get_symlink_target(fid)
+ mode = '120000'
+ elif kind == 'file':
+
+ if tree.is_executable(fid):
+ mode = '100755'
+ else:
+ mode = '100644'
+
+ # is the blog already exported?
+ if h in filenodes:
+ mark = filenodes[h]
+ final.append((mode, mark, path))
+ continue
+
+ d = tree.get_file_text(fid)
+ elif kind == 'directory':
+ continue
+ else:
+ die("Unhandled kind '%s' for path '%s'" % (kind, path))
+
+ mark = marks.next_mark()
+ filenodes[h] = mark
+
+ print "blob"
+ print "mark :%u" % mark
+ print "data %d" % len(d)
+ print d
+
+ final.append((mode, mark, path))
+
+ return final
+
+def export_branch(branch, name):
+ global prefix, dirname
+
+ ref = '%s/heads/%s' % (prefix, name)
+ tip = marks.get_tip(name)
+
+ repo = branch.repository
+ repo.lock_read()
+ revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward')
+ count = 0
+
+ revs = [revid for revid, _, _, _ in revs if not marks.is_marked(revid)]
+
+ for revid in revs:
+
+ rev = repo.get_revision(revid)
+
+ parents = rev.parent_ids
+ time = rev.timestamp
+ tz = rev.timezone
+ committer = rev.committer.encode('utf-8')
+ committer = "%s %u %s" % (fixup_user(committer), time, gittz(tz))
+ author = committer
+ msg = rev.message.encode('utf-8')
+
+ msg += '\n'
+
+ if len(parents) == 0:
+ parent = bzrlib.revision.NULL_REVISION
+ else:
+ parent = parents[0]
+
+ cur_tree = repo.revision_tree(revid)
+ prev = repo.revision_tree(parent)
+ modified, removed = get_filechanges(cur_tree, prev)
+
+ modified_final = export_files(cur_tree, modified)
+
+ if len(parents) == 0:
+ print 'reset %s' % ref
+
+ print "commit %s" % ref
+ print "mark :%d" % (marks.get_mark(revid))
+ print "author %s" % (author)
+ print "committer %s" % (committer)
+ print "data %d" % (len(msg))
+ print msg
+
+ for i, p in enumerate(parents):
+ try:
+ m = rev_to_mark(p)
+ except KeyError:
+ # ghost?
+ continue
+ if i == 0:
+ print "from :%s" % m
+ else:
+ print "merge :%s" % m
+
+ for f in modified_final:
+ print "M %s :%u %s" % f
+ for f in removed:
+ print "D %s" % (f)
+ print
+
+ count += 1
+ if (count % 100 == 0):
+ print "progress revision %s (%d/%d)" % (revid, count, len(revs))
+ print "#############################################################"
+
+ repo.unlock()
+
+ revid = branch.last_revision()
+
+ # make sure the ref is updated
+ print "reset %s" % ref
+ print "from :%u" % rev_to_mark(revid)
+ print
+
+ marks.set_tip(name, revid)
+
+def export_tag(repo, name):
+ global tags
+ try:
+ print "reset refs/tags/%s" % name
+ print "from :%u" % rev_to_mark(tags[name])
+ print
+ except KeyError:
+ warn("TODO: fetch tag '%s'" % name)
+
+def do_import(parser):
+ global dirname
+
+ branch = parser.repo
+ path = os.path.join(dirname, 'marks-git')
+
+ print "feature done"
+ if os.path.exists(path):
+ print "feature import-marks=%s" % path
+ print "feature export-marks=%s" % path
+ sys.stdout.flush()
+
+ while parser.check('import'):
+ ref = parser[1]
+ if ref.startswith('refs/heads/'):
+ name = ref[len('refs/heads/'):]
+ export_branch(branch, name)
+ if ref.startswith('refs/tags/'):
+ name = ref[len('refs/tags/'):]
+ export_tag(branch, name)
+ parser.next()
+
+ print 'done'
+
+ sys.stdout.flush()
+
+def parse_blob(parser):
+ global blob_marks
+
+ parser.next()
+ mark = parser.get_mark()
+ parser.next()
+ data = parser.get_data()
+ blob_marks[mark] = data
+ parser.next()
+
+class CustomTree():
+
+ def __init__(self, repo, revid, parents, files):
+ global files_cache
+
+ self.repo = repo
+ self.revid = revid
+ self.parents = parents
+ self.updates = {}
+
+ def copy_tree(revid):
+ files = files_cache[revid] = {}
+ tree = repo.repository.revision_tree(revid)
+ repo.lock_read()
+ try:
+ for path, entry in tree.iter_entries_by_dir():
+ files[path] = entry.file_id
+ finally:
+ repo.unlock()
+ return files
+
+ if len(parents) == 0:
+ self.base_id = bzrlib.revision.NULL_REVISION
+ self.base_files = {}
+ else:
+ self.base_id = parents[0]
+ self.base_files = files_cache.get(self.base_id, None)
+ if not self.base_files:
+ self.base_files = copy_tree(self.base_id)
+
+ self.files = files_cache[revid] = self.base_files.copy()
+
+ for path, f in files.iteritems():
+ fid = self.files.get(path, None)
+ if not fid:
+ fid = bzrlib.generate_ids.gen_file_id(path)
+ f['path'] = path
+ self.updates[fid] = f
+
+ def last_revision(self):
+ return self.base_id
+
+ def iter_changes(self):
+ changes = []
+
+ def get_parent(dirname, basename):
+ parent_fid = self.base_files.get(dirname, None)
+ if parent_fid:
+ return parent_fid
+ parent_fid = self.files.get(dirname, None)
+ if parent_fid:
+ return parent_fid
+ if basename == '':
+ return None
+ fid = bzrlib.generate_ids.gen_file_id(path)
+ d = add_entry(fid, dirname, 'directory')
+ return fid
+
+ def add_entry(fid, path, kind, mode = None):
+ dirname, basename = os.path.split(path)
+ parent_fid = get_parent(dirname, basename)
+
+ executable = False
+ if mode == '100755':
+ executable = True
+ elif mode == '120000':
+ kind = 'symlink'
+
+ change = (fid,
+ (None, path),
+ True,
+ (False, True),
+ (None, parent_fid),
+ (None, basename),
+ (None, kind),
+ (None, executable))
+ self.files[path] = change[0]
+ changes.append(change)
+ return change
+
+ def update_entry(fid, path, kind, mode = None):
+ dirname, basename = os.path.split(path)
+ parent_fid = get_parent(dirname, basename)
+
+ executable = False
+ if mode == '100755':
+ executable = True
+ elif mode == '120000':
+ kind = 'symlink'
+
+ change = (fid,
+ (path, path),
+ True,
+ (True, True),
+ (None, parent_fid),
+ (None, basename),
+ (None, kind),
+ (None, executable))
+ self.files[path] = change[0]
+ changes.append(change)
+ return change
+
+ def remove_entry(fid, path, kind):
+ dirname, basename = os.path.split(path)
+ parent_fid = get_parent(dirname, basename)
+ change = (fid,
+ (path, None),
+ True,
+ (True, False),
+ (parent_fid, None),
+ (None, None),
+ (None, None),
+ (None, None))
+ del self.files[path]
+ changes.append(change)
+ return change
+
+ for fid, f in self.updates.iteritems():
+ path = f['path']
+
+ if 'deleted' in f:
+ remove_entry(fid, path, 'file')
+ continue
+
+ if path in self.base_files:
+ update_entry(fid, path, 'file', f['mode'])
+ else:
+ add_entry(fid, path, 'file', f['mode'])
+
+ return changes
+
+ def get_file_with_stat(self, file_id, path=None):
+ return (StringIO.StringIO(self.updates[file_id]['data']), None)
+
+ def get_symlink_target(self, file_id):
+ return self.updates[file_id]['data']
+
+def parse_commit(parser):
+ global marks, blob_marks, bmarks, parsed_refs
+ global mode
+
+ parents = []
+
+ ref = parser[1]
+ parser.next()
+
+ if ref != 'refs/heads/master':
+ die("bzr doesn't support multiple branches; use 'master'")
+
+ commit_mark = parser.get_mark()
+ parser.next()
+ author = parser.get_author()
+ parser.next()
+ committer = parser.get_author()
+ parser.next()
+ data = parser.get_data()
+ parser.next()
+ if parser.check('from'):
+ parents.append(parser.get_mark())
+ parser.next()
+ while parser.check('merge'):
+ parents.append(parser.get_mark())
+ parser.next()
+
+ files = {}
+
+ for line in parser:
+ if parser.check('M'):
+ t, m, mark_ref, path = line.split(' ', 3)
+ mark = int(mark_ref[1:])
+ f = { 'mode' : m, 'data' : blob_marks[mark] }
+ elif parser.check('D'):
+ t, path = line.split(' ')
+ f = { 'deleted' : True }
+ else:
+ die('Unknown file command: %s' % line)
+ files[path] = f
+
+ repo = parser.repo
+
+ committer, date, tz = committer
+ parents = [str(mark_to_rev(p)) for p in parents]
+ revid = bzrlib.generate_ids.gen_revision_id(committer, date)
+ props = {}
+ props['branch-nick'] = repo.nick
+
+ mtree = CustomTree(repo, revid, parents, files)
+ changes = mtree.iter_changes()
+
+ repo.lock_write()
+ try:
+ builder = repo.get_commit_builder(parents, None, date, tz, committer, props, revid)
+ try:
+ list(builder.record_iter_changes(mtree, mtree.last_revision(), changes))
+ builder.finish_inventory()
+ builder.commit(data.decode('utf-8', 'replace'))
+ except Exception, e:
+ builder.abort()
+ raise
+ finally:
+ repo.unlock()
+
+ parsed_refs[ref] = revid
+ marks.new_mark(revid, commit_mark)
+
+def parse_reset(parser):
+ global parsed_refs
+
+ ref = parser[1]
+ parser.next()
+
+ if ref != 'refs/heads/master':
+ die("bzr doesn't support multiple branches; use 'master'")
+
+ # ugh
+ if parser.check('commit'):
+ parse_commit(parser)
+ return
+ if not parser.check('from'):
+ return
+ from_mark = parser.get_mark()
+ parser.next()
+
+ parsed_refs[ref] = mark_to_rev(from_mark)
+
+def do_export(parser):
+ global parsed_refs, dirname, peer
+
+ parser.next()
+
+ for line in parser.each_block('done'):
+ if parser.check('blob'):
+ parse_blob(parser)
+ elif parser.check('commit'):
+ parse_commit(parser)
+ elif parser.check('reset'):
+ parse_reset(parser)
+ elif parser.check('tag'):
+ pass
+ elif parser.check('feature'):
+ pass
+ else:
+ die('unhandled export command: %s' % line)
+
+ repo = parser.repo
+
+ for ref, revid in parsed_refs.iteritems():
+ if ref == 'refs/heads/master':
+ repo.generate_revision_history(revid, marks.get_tip('master'))
+ revno, revid = repo.last_revision_info()
+ if peer:
+ if hasattr(peer, "import_last_revision_info_and_tags"):
+ peer.import_last_revision_info_and_tags(repo, revno, revid)
+ else:
+ peer.import_last_revision_info(repo.repository, revno, revid)
+ wt = peer.bzrdir.open_workingtree()
+ else:
+ wt = repo.bzrdir.open_workingtree()
+ wt.update()
+ print "ok %s" % ref
+ print
+
+def do_capabilities(parser):
+ global dirname
+
+ print "import"
+ print "export"
+ print "refspec refs/heads/*:%s/heads/*" % prefix
+
+ path = os.path.join(dirname, 'marks-git')
+
+ if os.path.exists(path):
+ print "*import-marks %s" % path
+ print "*export-marks %s" % path
+
+ print
+
+def do_list(parser):
+ global tags
+ print "? refs/heads/%s" % 'master'
+ for tag, revid in parser.repo.tags.get_tag_dict().items():
+ print "? refs/tags/%s" % tag
+ tags[tag] = revid
+ print "@refs/heads/%s HEAD" % 'master'
+ print
+
+def get_repo(url, alias):
+ global dirname, peer
+
+ origin = bzrlib.bzrdir.BzrDir.open(url)
+ branch = origin.open_branch()
+
+ if not isinstance(origin.transport, bzrlib.transport.local.LocalTransport):
+ clone_path = os.path.join(dirname, 'clone')
+ remote_branch = branch
+ if os.path.exists(clone_path):
+ # pull
+ d = bzrlib.bzrdir.BzrDir.open(clone_path)
+ branch = d.open_branch()
+ result = branch.pull(remote_branch, [], None, False)
+ else:
+ # clone
+ d = origin.sprout(clone_path, None,
+ hardlink=True, create_tree_if_local=False,
+ source_branch=remote_branch)
+ branch = d.open_branch()
+ branch.bind(remote_branch)
+
+ peer = remote_branch
+ else:
+ peer = None
+
+ return branch
+
+def main(args):
+ global marks, prefix, dirname
+ global tags, filenodes
+ global blob_marks
+ global parsed_refs
+ global files_cache
+
+ alias = args[1]
+ url = args[2]
+
+ prefix = 'refs/bzr/%s' % alias
+ tags = {}
+ filenodes = {}
+ blob_marks = {}
+ parsed_refs = {}
+ files_cache = {}
+
+ gitdir = os.environ['GIT_DIR']
+ dirname = os.path.join(gitdir, 'bzr', alias)
+
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+
+ repo = get_repo(url, alias)
+
+ marks_path = os.path.join(dirname, 'marks-int')
+ marks = Marks(marks_path)
+
+ parser = Parser(repo)
+ for line in parser:
+ if parser.check('capabilities'):
+ do_capabilities(parser)
+ elif parser.check('list'):
+ do_list(parser)
+ elif parser.check('import'):
+ do_import(parser)
+ elif parser.check('export'):
+ do_export(parser)
+ else:
+ die('unhandled command: %s' % line)
+ sys.stdout.flush()
+
+ marks.store()
+
+sys.exit(main(sys.argv))
diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index 016cdadb4d..c7006000a6 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -31,7 +31,7 @@ import urllib
# hg:
# Emulate hg-git.
# Only hg bookmarks are exported as git branches.
-# Commits are modified to preserve hg information and allow biridectionality.
+# Commits are modified to preserve hg information and allow bidirectionality.
#
NAME_RE = re.compile('^([^<>]+)')
diff --git a/contrib/remote-helpers/test-bzr.sh b/contrib/remote-helpers/test-bzr.sh
new file mode 100755
index 0000000000..70aa8a010a
--- /dev/null
+++ b/contrib/remote-helpers/test-bzr.sh
@@ -0,0 +1,143 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+test_description='Test remote-bzr'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+ skip_all='skipping remote-bzr tests; python not available'
+ test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import bzrlib'; then
+ skip_all='skipping remote-bzr tests; bzr not available'
+ test_done
+fi
+
+cmd='
+import bzrlib
+bzrlib.initialize()
+import bzrlib.plugin
+bzrlib.plugin.load_plugins()
+import bzrlib.plugins.fastimport
+'
+
+if ! "$PYTHON_PATH" -c "$cmd"; then
+ echo "consider setting BZR_PLUGIN_PATH=$HOME/.bazaar/plugins" 1>&2
+ skip_all='skipping remote-bzr tests; bzr-fastimport not available'
+ test_done
+fi
+
+check () {
+ (cd $1 &&
+ git log --format='%s' -1 &&
+ git symbolic-ref HEAD) > actual &&
+ (echo $2 &&
+ echo "refs/heads/$3") > expected &&
+ test_cmp expected actual
+}
+
+bzr whoami "A U Thor <author@example.com>"
+
+test_expect_success 'cloning' '
+ (bzr init bzrrepo &&
+ cd bzrrepo &&
+ echo one > content &&
+ bzr add content &&
+ bzr commit -m one
+ ) &&
+
+ git clone "bzr::$PWD/bzrrepo" gitrepo &&
+ check gitrepo one master
+'
+
+test_expect_success 'pulling' '
+ (cd bzrrepo &&
+ echo two > content &&
+ bzr commit -m two
+ ) &&
+
+ (cd gitrepo && git pull) &&
+
+ check gitrepo two master
+'
+
+test_expect_success 'pushing' '
+ (cd gitrepo &&
+ echo three > content &&
+ git commit -a -m three &&
+ git push
+ ) &&
+
+ echo three > expected &&
+ cat bzrrepo/content > actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'roundtrip' '
+ (cd gitrepo &&
+ git pull &&
+ git log --format="%s" -1 origin/master > actual) &&
+ echo three > expected &&
+ test_cmp expected actual &&
+
+ (cd gitrepo && git push && git pull) &&
+
+ (cd bzrrepo &&
+ echo four > content &&
+ bzr commit -m four
+ ) &&
+
+ (cd gitrepo && git pull && git push) &&
+
+ check gitrepo four master &&
+
+ (cd gitrepo &&
+ echo five > content &&
+ git commit -a -m five &&
+ git push && git pull
+ ) &&
+
+ (cd bzrrepo && bzr revert) &&
+
+ echo five > expected &&
+ cat bzrrepo/content > actual &&
+ test_cmp expected actual
+'
+
+cat > expected <<EOF
+100644 blob 54f9d6da5c91d556e6b54340b1327573073030af content
+100755 blob 68769579c3eaadbe555379b9c3538e6628bae1eb executable
+120000 blob 6b584e8ece562ebffc15d38808cd6b98fc3d97ea link
+EOF
+
+test_expect_success 'special modes' '
+ (cd bzrrepo &&
+ echo exec > executable
+ chmod +x executable &&
+ bzr add executable
+ bzr commit -m exec &&
+ ln -s content link
+ bzr add link
+ bzr commit -m link &&
+ mkdir dir &&
+ bzr add dir &&
+ bzr commit -m dir) &&
+
+ (cd gitrepo &&
+ git pull
+ git ls-tree HEAD > ../actual) &&
+
+ test_cmp expected actual &&
+
+ (cd gitrepo &&
+ git cat-file -p HEAD:link > ../actual) &&
+
+ echo -n content > expected &&
+ test_cmp expected actual
+'
+
+test_done
diff --git a/contrib/remote-helpers/test-hg-bidi.sh b/contrib/remote-helpers/test-hg-bidi.sh
index a94eb28092..1d61982436 100755
--- a/contrib/remote-helpers/test-hg-bidi.sh
+++ b/contrib/remote-helpers/test-hg-bidi.sh
@@ -6,7 +6,7 @@
# https://bitbucket.org/durin42/hg-git/src
#
-test_description='Test biridectionality of remote-hg'
+test_description='Test bidirectionality of remote-hg'
. ./test-lib.sh
diff --git a/contrib/svn-fe/svnrdump_sim.py b/contrib/svn-fe/svnrdump_sim.py
index 1cfac4a6f8..17cf6f961f 100755
--- a/contrib/svn-fe/svnrdump_sim.py
+++ b/contrib/svn-fe/svnrdump_sim.py
@@ -7,6 +7,10 @@ to the highest revision that should be available.
"""
import sys, os
+if sys.hexversion < 0x02040000:
+ # The limiter is the ValueError() calls. This may be too conservative
+ sys.stderr.write("svnrdump-sim.py: requires Python 2.4 or later.\n")
+ sys.exit(1)
def getrevlimit():
var = 'SVNRMAX'
diff --git a/ctype.c b/ctype.c
index 935327164b..0bfebb4e75 100644
--- a/ctype.c
+++ b/ctype.c
@@ -11,18 +11,21 @@ enum {
D = GIT_DIGIT,
G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */
R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | */
- P = GIT_PATHSPEC_MAGIC /* other non-alnum, except for ] and } */
+ P = GIT_PATHSPEC_MAGIC, /* other non-alnum, except for ] and } */
+ X = GIT_CNTRL,
+ U = GIT_PUNCT,
+ Z = GIT_CNTRL | GIT_SPACE
};
-unsigned char sane_ctype[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0, /* 0.. 15 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16.. 31 */
+const unsigned char sane_ctype[256] = {
+ X, X, X, X, X, X, X, X, X, Z, Z, X, X, Z, X, X, /* 0.. 15 */
+ X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 16.. 31 */
S, P, P, P, R, P, P, P, R, R, G, R, P, P, R, P, /* 32.. 47 */
D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, G, /* 48.. 63 */
P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */
- A, A, A, A, A, A, A, A, A, A, A, G, G, 0, R, P, /* 80.. 95 */
+ A, A, A, A, A, A, A, A, A, A, A, G, G, U, R, P, /* 80.. 95 */
P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */
- A, A, A, A, A, A, A, A, A, A, A, R, R, 0, P, 0, /* 112..127 */
+ A, A, A, A, A, A, A, A, A, A, A, R, R, U, P, X, /* 112..127 */
/* Nothing in the 128.. range */
};
diff --git a/dir.c b/dir.c
index 5a83aa7897..3780755047 100644
--- a/dir.c
+++ b/dir.c
@@ -8,6 +8,7 @@
#include "cache.h"
#include "dir.h"
#include "refs.h"
+#include "wildmatch.h"
struct path_simplify {
int len;
@@ -34,10 +35,33 @@ int fnmatch_icase(const char *pattern, const char *string, int flags)
return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
}
+inline int git_fnmatch(const char *pattern, const char *string,
+ int flags, int prefix)
+{
+ int fnm_flags = 0;
+ if (flags & GFNM_PATHNAME)
+ fnm_flags |= FNM_PATHNAME;
+ if (prefix > 0) {
+ if (strncmp(pattern, string, prefix))
+ return FNM_NOMATCH;
+ pattern += prefix;
+ string += prefix;
+ }
+ if (flags & GFNM_ONESTAR) {
+ int pattern_len = strlen(++pattern);
+ int string_len = strlen(string);
+ return string_len < pattern_len ||
+ strcmp(pattern,
+ string + string_len - pattern_len);
+ }
+ return fnmatch(pattern, string, fnm_flags);
+}
+
static size_t common_prefix_len(const char **pathspec)
{
const char *n, *first;
size_t max = 0;
+ int literal = limit_pathspec_to_literal();
if (!pathspec)
return max;
@@ -47,7 +71,7 @@ static size_t common_prefix_len(const char **pathspec)
size_t i, len = 0;
for (i = 0; first == n || i < max; i++) {
char c = n[i];
- if (!c || c != first[i] || is_glob_special(c))
+ if (!c || c != first[i] || (!literal && is_glob_special(c)))
break;
if (c == '/')
len = i + 1;
@@ -117,6 +141,7 @@ int within_depth(const char *name, int namelen,
static int match_one(const char *match, const char *name, int namelen)
{
int matchlen;
+ int literal = limit_pathspec_to_literal();
/* If the match was just the prefix, we matched */
if (!*match)
@@ -126,7 +151,7 @@ static int match_one(const char *match, const char *name, int namelen)
for (;;) {
unsigned char c1 = tolower(*match);
unsigned char c2 = tolower(*name);
- if (c1 == '\0' || is_glob_special(c1))
+ if (c1 == '\0' || (!literal && is_glob_special(c1)))
break;
if (c1 != c2)
return 0;
@@ -138,7 +163,7 @@ static int match_one(const char *match, const char *name, int namelen)
for (;;) {
unsigned char c1 = *match;
unsigned char c2 = *name;
- if (c1 == '\0' || is_glob_special(c1))
+ if (c1 == '\0' || (!literal && is_glob_special(c1)))
break;
if (c1 != c2)
return 0;
@@ -148,14 +173,16 @@ static int match_one(const char *match, const char *name, int namelen)
}
}
-
/*
* If we don't match the matchstring exactly,
* we need to match by fnmatch
*/
matchlen = strlen(match);
- if (strncmp_icase(match, name, matchlen))
+ if (strncmp_icase(match, name, matchlen)) {
+ if (literal)
+ return 0;
return !fnmatch_icase(match, name, 0) ? MATCHED_FNMATCH : 0;
+ }
if (namelen == matchlen)
return MATCHED_EXACTLY;
@@ -230,7 +257,10 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
return MATCHED_RECURSIVELY;
}
- if (item->use_wildcard && !fnmatch(match, name, 0))
+ if (item->nowildcard_len < item->len &&
+ !git_fnmatch(match, name,
+ item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+ item->nowildcard_len - prefix))
return MATCHED_FNMATCH;
return 0;
@@ -595,7 +625,8 @@ int match_pathname(const char *pathname, int pathlen,
namelen -= prefix;
}
- return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
+ return wildmatch(pattern, name,
+ ignore_case ? FNM_CASEFOLD : 0) == 0;
}
/* Scan the list and let the last match determine the fate.
@@ -1429,9 +1460,18 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
item->match = path;
item->len = strlen(path);
- item->use_wildcard = !no_wildcard(path);
- if (item->use_wildcard)
- pathspec->has_wildcard = 1;
+ item->flags = 0;
+ if (limit_pathspec_to_literal()) {
+ item->nowildcard_len = item->len;
+ } else {
+ item->nowildcard_len = simple_length(path);
+ if (item->nowildcard_len < item->len) {
+ pathspec->has_wildcard = 1;
+ if (path[item->nowildcard_len] == '*' &&
+ no_wildcard(path + item->nowildcard_len + 1))
+ item->flags |= PATHSPEC_ONESTAR;
+ }
+ }
}
qsort(pathspec->items, pathspec->nr,
@@ -1445,3 +1485,11 @@ void free_pathspec(struct pathspec *pathspec)
free(pathspec->items);
pathspec->items = NULL;
}
+
+int limit_pathspec_to_literal(void)
+{
+ static int flag = -1;
+ if (flag < 0)
+ flag = git_env_bool(GIT_LITERAL_PATHSPECS_ENVIRONMENT, 0);
+ return flag;
+}
diff --git a/dir.h b/dir.h
index f5c89e3b80..ab5af42b2e 100644
--- a/dir.h
+++ b/dir.h
@@ -139,4 +139,13 @@ extern int strcmp_icase(const char *a, const char *b);
extern int strncmp_icase(const char *a, const char *b, size_t count);
extern int fnmatch_icase(const char *pattern, const char *string, int flags);
+/*
+ * The prefix part of pattern must not contains wildcards.
+ */
+#define GFNM_PATHNAME 1 /* similar to FNM_PATHNAME */
+#define GFNM_ONESTAR 2 /* there is only _one_ wildcard, a star */
+
+extern int git_fnmatch(const char *pattern, const char *string,
+ int flags, int prefix);
+
#endif
diff --git a/fsck.c b/fsck.c
index 7395ef6a42..99c0497674 100644
--- a/fsck.c
+++ b/fsck.c
@@ -142,6 +142,9 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
int has_null_sha1 = 0;
int has_full_path = 0;
int has_empty_name = 0;
+ int has_dot = 0;
+ int has_dotdot = 0;
+ int has_dotgit = 0;
int has_zero_pad = 0;
int has_bad_modes = 0;
int has_dup_entries = 0;
@@ -168,6 +171,12 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
has_full_path = 1;
if (!*name)
has_empty_name = 1;
+ if (!strcmp(name, "."))
+ has_dot = 1;
+ if (!strcmp(name, ".."))
+ has_dotdot = 1;
+ if (!strcmp(name, ".git"))
+ has_dotgit = 1;
has_zero_pad |= *(char *)desc.buffer == '0';
update_tree_entry(&desc);
@@ -217,6 +226,12 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
retval += error_func(&item->object, FSCK_WARN, "contains full pathnames");
if (has_empty_name)
retval += error_func(&item->object, FSCK_WARN, "contains empty pathname");
+ if (has_dot)
+ retval += error_func(&item->object, FSCK_WARN, "contains '.'");
+ if (has_dotdot)
+ retval += error_func(&item->object, FSCK_WARN, "contains '..'");
+ if (has_dotgit)
+ retval += error_func(&item->object, FSCK_WARN, "contains '.git'");
if (has_zero_pad)
retval += error_func(&item->object, FSCK_WARN, "contains zero-padded file modes");
if (has_bad_modes)
diff --git a/git-compat-util.h b/git-compat-util.h
index 610e6b7ea4..e5a4b7450b 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -290,6 +290,17 @@ extern NORETURN void die_errno(const char *err, ...) __attribute__((format (prin
extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
+/*
+ * Let callers be aware of the constant return value; this can help
+ * gcc with -Wuninitialized analysis. We have to restrict this trick to
+ * gcc, though, because of the variadic macro and the magic ## comma pasting
+ * behavior. But since we're only trying to help gcc, anyway, it's OK; other
+ * compilers will fall back to using the function as usual.
+ */
+#ifdef __GNUC__
+#define error(fmt, ...) (error((fmt), ##__VA_ARGS__), -1)
+#endif
+
extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
extern void set_error_routine(void (*routine)(const char *err, va_list params));
@@ -517,13 +528,19 @@ extern const char tolower_trans_tbl[256];
#undef isupper
#undef tolower
#undef toupper
-extern unsigned char sane_ctype[256];
+#undef iscntrl
+#undef ispunct
+#undef isxdigit
+
+extern const unsigned char sane_ctype[256];
#define GIT_SPACE 0x01
#define GIT_DIGIT 0x02
#define GIT_ALPHA 0x04
#define GIT_GLOB_SPECIAL 0x08
#define GIT_REGEX_SPECIAL 0x10
#define GIT_PATHSPEC_MAGIC 0x20
+#define GIT_CNTRL 0x40
+#define GIT_PUNCT 0x80
#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
#define isascii(x) (((x) & ~0x7f) == 0)
#define isspace(x) sane_istest(x,GIT_SPACE)
@@ -535,6 +552,10 @@ extern unsigned char sane_ctype[256];
#define isupper(x) sane_iscase(x, 0)
#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL)
#define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL)
+#define iscntrl(x) (sane_istest(x,GIT_CNTRL))
+#define ispunct(x) sane_istest(x, GIT_PUNCT | GIT_REGEX_SPECIAL | \
+ GIT_GLOB_SPECIAL | GIT_PATHSPEC_MAGIC)
+#define isxdigit(x) (hexval_table[x] != -1)
#define tolower(x) sane_case((unsigned char)(x), 0x20)
#define toupper(x) sane_case((unsigned char)(x), 0)
#define is_pathspec_magic(x) sane_istest(x,GIT_PATHSPEC_MAGIC)
@@ -643,8 +664,12 @@ int rmdir_or_warn(const char *path);
*/
int remove_or_warn(unsigned int mode, const char *path);
-/* Call access(2), but warn for any error besides ENOENT. */
+/*
+ * Call access(2), but warn for any error except "missing file"
+ * (ENOENT or ENOTDIR).
+ */
int access_or_warn(const char *path, int mode);
+int access_or_die(const char *path, int mode);
/* Warn on an inaccessible file that ought to be accessible */
void warn_on_inaccessible(const char *path);
diff --git a/git-p4.py b/git-p4.py
index 551aec9417..69f1452cf8 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -8,7 +8,13 @@
# License: MIT <http://www.opensource.org/licenses/mit-license.php>
#
-import optparse, sys, os, marshal, subprocess, shelve
+import sys
+if sys.hexversion < 0x02040000:
+ # The limiter is the subprocess module
+ sys.stderr.write("git-p4: requires Python 2.4 or later.\n")
+ sys.exit(1)
+
+import optparse, os, marshal, subprocess, shelve
import tempfile, getopt, os.path, time, platform
import re, shutil
diff --git a/git-rebase--am.sh b/git-rebase--am.sh
index 392ebc9790..97f31dc7af 100644
--- a/git-rebase--am.sh
+++ b/git-rebase--am.sh
@@ -18,6 +18,7 @@ esac
test -n "$rebase_root" && root_flag=--root
+ret=0
if test -n "$keep_empty"
then
# we have to do this the hard way. git format-patch completely squashes
@@ -25,13 +26,49 @@ then
# itself well to recording empty patches. fortunately, cherry-pick
# makes this easy
git cherry-pick --allow-empty "$revisions"
+ ret=$?
else
+ rm -f "$GIT_DIR/rebased-patches"
+
git format-patch -k --stdout --full-index --ignore-if-in-upstream \
--src-prefix=a/ --dst-prefix=b/ \
- --no-renames $root_flag "$revisions" |
- git am $git_am_opt --rebasing --resolvemsg="$resolvemsg"
-fi && move_to_original_branch
+ --no-renames $root_flag "$revisions" >"$GIT_DIR/rebased-patches"
+ ret=$?
+
+ if test 0 != $ret
+ then
+ rm -f "$GIT_DIR/rebased-patches"
+ case "$head_name" in
+ refs/heads/*)
+ git checkout -q "$head_name"
+ ;;
+ *)
+ git checkout -q "$orig_head"
+ ;;
+ esac
+
+ cat >&2 <<-EOF
+
+ git encountered an error while preparing the patches to replay
+ these revisions:
+
+ $revisions
+
+ As a result, git cannot rebase them.
+ EOF
+ exit $?
+ fi
+
+ git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" <"$GIT_DIR/rebased-patches"
+ ret=$?
+
+ rm -f "$GIT_DIR/rebased-patches"
+fi
+
+if test 0 != $ret
+then
+ test -d "$state_dir" && write_basic_state
+ exit $ret
+fi
-ret=$?
-test 0 != $ret -a -d "$state_dir" && write_basic_state
-exit $ret
+move_to_original_branch
diff --git a/git-remote-testgit b/git-remote-testgit
new file mode 100755
index 0000000000..b395c8de59
--- /dev/null
+++ b/git-remote-testgit
@@ -0,0 +1,90 @@
+#!/usr/bin/env bash
+# Copyright (c) 2012 Felipe Contreras
+
+alias=$1
+url=$2
+
+dir="$GIT_DIR/testgit/$alias"
+prefix="refs/testgit/$alias"
+
+default_refspec="refs/heads/*:${prefix}/heads/*"
+
+refspec="${GIT_REMOTE_TESTGIT_REFSPEC-$default_refspec}"
+
+test -z "$refspec" && prefix="refs"
+
+export GIT_DIR="$url/.git"
+
+mkdir -p "$dir"
+
+if test -z "$GIT_REMOTE_TESTGIT_NO_MARKS"
+then
+ gitmarks="$dir/git.marks"
+ testgitmarks="$dir/testgit.marks"
+ test -e "$gitmarks" || >"$gitmarks"
+ test -e "$testgitmarks" || >"$testgitmarks"
+ testgitmarks_args=( "--"{import,export}"-marks=$testgitmarks" )
+fi
+
+while read line
+do
+ case $line in
+ capabilities)
+ echo 'import'
+ echo 'export'
+ test -n "$refspec" && echo "refspec $refspec"
+ if test -n "$gitmarks"
+ then
+ echo "*import-marks $gitmarks"
+ echo "*export-marks $gitmarks"
+ fi
+ echo
+ ;;
+ list)
+ git for-each-ref --format='? %(refname)' 'refs/heads/'
+ head=$(git symbolic-ref HEAD)
+ echo "@$head HEAD"
+ echo
+ ;;
+ import*)
+ # read all import lines
+ while true
+ do
+ ref="${line#* }"
+ refs="$refs $ref"
+ read line
+ test "${line%% *}" != "import" && break
+ done
+
+ if test -n "$gitmarks"
+ then
+ echo "feature import-marks=$gitmarks"
+ echo "feature export-marks=$gitmarks"
+ fi
+ echo "feature done"
+ git fast-export "${testgitmarks_args[@]}" $refs |
+ sed -e "s#refs/heads/#${prefix}/heads/#g"
+ echo "done"
+ ;;
+ export)
+ before=$(git for-each-ref --format='%(refname) %(objectname)')
+
+ git fast-import "${testgitmarks_args[@]}" --quiet
+
+ after=$(git for-each-ref --format='%(refname) %(objectname)')
+
+ # figure out which refs were updated
+ join -e 0 -o '0 1.2 2.2' -a 2 <(echo "$before") <(echo "$after") |
+ while read ref a b
+ do
+ test $a == $b && continue
+ echo "ok $ref"
+ done
+
+ echo
+ ;;
+ '')
+ exit
+ ;;
+ esac
+done
diff --git a/git-remote-testgit.py b/git-remote-testpy.py
index 5f3ebd244d..e4533b187d 100644
--- a/git-remote-testgit.py
+++ b/git-remote-testpy.py
@@ -31,6 +31,11 @@ from git_remote_helpers.git.exporter import GitExporter
from git_remote_helpers.git.importer import GitImporter
from git_remote_helpers.git.non_local import NonLocalGit
+if sys.hexversion < 0x01050200:
+ # os.makedirs() is the limiter
+ sys.stderr.write("git-remote-testgit: requires Python 1.5.2 or later.\n")
+ sys.exit(1)
+
def get_repo(alias, url):
"""Returns a git repository object initialized for usage.
"""
@@ -91,7 +96,7 @@ def do_capabilities(repo, args):
if not os.path.exists(dirname):
os.makedirs(dirname)
- path = os.path.join(dirname, 'testgit.marks')
+ path = os.path.join(dirname, 'git.marks')
print "*export-marks %s" % path
if os.path.exists(path):
diff --git a/git-submodule.sh b/git-submodule.sh
index 2365149d0b..22ec5b63b4 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -8,7 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: $dashless [--quiet] init [--] [<path>...]
- or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+ or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: $dashless [--quiet] foreach [--recursive] <command>
or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
@@ -26,6 +26,7 @@ cached=
recursive=
init=
files=
+remote=
nofetch=
update=
prefix=
@@ -153,6 +154,32 @@ die_if_unmatched ()
}
#
+# Print a submodule configuration setting
+#
+# $1 = submodule name
+# $2 = option name
+# $3 = default value
+#
+# Checks in the usual git-config places first (for overrides),
+# otherwise it falls back on .gitmodules. This allows you to
+# distribute project-wide defaults in .gitmodules, while still
+# customizing individual repositories if necessary. If the option is
+# not in .gitmodules either, print a default value.
+#
+get_submodule_config () {
+ name="$1"
+ option="$2"
+ default="$3"
+ value=$(git config submodule."$name"."$option")
+ if test -z "$value"
+ then
+ value=$(git config -f .gitmodules submodule."$name"."$option")
+ fi
+ printf '%s' "${value:-$default}"
+}
+
+
+#
# Map submodule path to submodule name
#
# $1 = path
@@ -390,6 +417,10 @@ Use -f if you really want to add it." >&2
git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
git config -f .gitmodules submodule."$sm_name".url "$repo" &&
+ if test -n "$branch"
+ then
+ git config -f .gitmodules submodule."$sm_name".branch "$branch"
+ fi &&
git add --force .gitmodules ||
die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
}
@@ -533,6 +564,9 @@ cmd_update()
-i|--init)
init=1
;;
+ --remote)
+ remote=1
+ ;;
-N|--no-fetch)
nofetch=1
;;
@@ -593,6 +627,7 @@ cmd_update()
fi
name=$(module_name "$sm_path") || exit
url=$(git config submodule."$name".url)
+ branch=$(get_submodule_config "$name" branch master)
if ! test -z "$update"
then
update_module=$update
@@ -627,6 +662,20 @@ Maybe you want to use 'update --init'?")"
die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")"
fi
+ if test -n "$remote"
+ then
+ if test -z "$nofetch"
+ then
+ # Fetch remote before determining tracking $sha1
+ (clear_local_git_env; cd "$sm_path" && git-fetch) ||
+ die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
+ fi
+ remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote)
+ sha1=$(clear_local_git_env; cd "$sm_path" &&
+ git rev-parse --verify "${remote_name}/${branch}") ||
+ die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
+ fi
+
if test "$subsha1" != "$sha1" -o -n "$force"
then
subforce=$force
diff --git a/git.c b/git.c
index d33f9b32a2..ed66c660d1 100644
--- a/git.c
+++ b/git.c
@@ -135,6 +135,14 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
git_config_push_parameter((*argv)[1]);
(*argv)++;
(*argc)--;
+ } else if (!strcmp(cmd, "--literal-pathspecs")) {
+ setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "1", 1);
+ if (envchanged)
+ *envchanged = 1;
+ } else if (!strcmp(cmd, "--no-literal-pathspecs")) {
+ setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "0", 1);
+ if (envchanged)
+ *envchanged = 1;
} else {
fprintf(stderr, "Unknown option: %s\n", cmd);
usage(git_usage_string);
diff --git a/git_remote_helpers/git/__init__.py b/git_remote_helpers/git/__init__.py
index e69de29bb2..1dbb1b0148 100644
--- a/git_remote_helpers/git/__init__.py
+++ b/git_remote_helpers/git/__init__.py
@@ -0,0 +1,5 @@
+import sys
+if sys.hexversion < 0x02040000:
+ # The limiter is the subprocess module
+ sys.stderr.write("git_remote_helpers: requires Python 2.4 or later.\n")
+ sys.exit(1)
diff --git a/git_remote_helpers/git/importer.py b/git_remote_helpers/git/importer.py
index 5c6b595e16..e28cc8f986 100644
--- a/git_remote_helpers/git/importer.py
+++ b/git_remote_helpers/git/importer.py
@@ -39,7 +39,7 @@ class GitImporter(object):
gitdir = self.repo.gitpath
else:
gitdir = os.path.abspath(os.path.join(dirname, '.git'))
- path = os.path.abspath(os.path.join(dirname, 'git.marks'))
+ path = os.path.abspath(os.path.join(dirname, 'testgit.marks'))
if not os.path.exists(dirname):
os.makedirs(dirname)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 656b324fb7..c6bafe6ead 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1556,7 +1556,7 @@ sub sanitize {
return undef unless defined $str;
$str = to_utf8($str);
- $str =~ s|([[:cntrl:]])|($1 =~ /[\t\n\r]/ ? $1 : quot_cec($1))|eg;
+ $str =~ s|([[:cntrl:]])|(index("\t\n\r", $1) != -1 ? $1 : quot_cec($1))|eg;
return $str;
}
diff --git a/http-push.c b/http-push.c
index 8701c1215d..9923441a4e 100644
--- a/http-push.c
+++ b/http-push.c
@@ -172,28 +172,7 @@ enum dav_header_flag {
static char *xml_entities(const char *s)
{
struct strbuf buf = STRBUF_INIT;
- while (*s) {
- size_t len = strcspn(s, "\"<>&");
- strbuf_add(&buf, s, len);
- s += len;
- switch (*s) {
- case '"':
- strbuf_addstr(&buf, "&quot;");
- break;
- case '<':
- strbuf_addstr(&buf, "&lt;");
- break;
- case '>':
- strbuf_addstr(&buf, "&gt;");
- break;
- case '&':
- strbuf_addstr(&buf, "&amp;");
- break;
- case 0:
- return strbuf_detach(&buf, NULL);
- }
- s++;
- }
+ strbuf_addstr_xml_quoted(&buf, s);
return strbuf_detach(&buf, NULL);
}
diff --git a/imap-send.c b/imap-send.c
index d42e471297..e521e2fd22 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -69,8 +69,7 @@ struct store {
};
struct msg_data {
- char *data;
- int len;
+ struct strbuf data;
unsigned char flags;
};
@@ -1264,45 +1263,49 @@ static int imap_make_flags(int flags, char *buf)
return d;
}
-static void lf_to_crlf(struct msg_data *msg)
+static void lf_to_crlf(struct strbuf *msg)
{
+ size_t new_len;
char *new;
int i, j, lfnum = 0;
- if (msg->data[0] == '\n')
+ if (msg->buf[0] == '\n')
lfnum++;
for (i = 1; i < msg->len; i++) {
- if (msg->data[i - 1] != '\r' && msg->data[i] == '\n')
+ if (msg->buf[i - 1] != '\r' && msg->buf[i] == '\n')
lfnum++;
}
- new = xmalloc(msg->len + lfnum);
- if (msg->data[0] == '\n') {
+ new_len = msg->len + lfnum;
+ new = xmalloc(new_len + 1);
+ if (msg->buf[0] == '\n') {
new[0] = '\r';
new[1] = '\n';
i = 1;
j = 2;
} else {
- new[0] = msg->data[0];
+ new[0] = msg->buf[0];
i = 1;
j = 1;
}
for ( ; i < msg->len; i++) {
- if (msg->data[i] != '\n') {
- new[j++] = msg->data[i];
+ if (msg->buf[i] != '\n') {
+ new[j++] = msg->buf[i];
continue;
}
- if (msg->data[i - 1] != '\r')
+ if (msg->buf[i - 1] != '\r')
new[j++] = '\r';
/* otherwise it already had CR before */
new[j++] = '\n';
}
- msg->len += lfnum;
- free(msg->data);
- msg->data = new;
+ strbuf_attach(msg, new, new_len, new_len + 1);
}
-static int imap_store_msg(struct store *gctx, struct msg_data *data)
+/*
+ * Store msg to IMAP. Also detach and free the data from msg->data,
+ * leaving msg->data empty.
+ */
+static int imap_store_msg(struct store *gctx, struct msg_data *msg)
{
struct imap_store *ctx = (struct imap_store *)gctx;
struct imap *imap = ctx->imap;
@@ -1311,16 +1314,15 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data)
int ret, d;
char flagstr[128];
- lf_to_crlf(data);
+ lf_to_crlf(&msg->data);
memset(&cb, 0, sizeof(cb));
- cb.dlen = data->len;
- cb.data = xmalloc(cb.dlen);
- memcpy(cb.data, data->data, data->len);
+ cb.dlen = msg->data.len;
+ cb.data = strbuf_detach(&msg->data, NULL);
d = 0;
- if (data->flags) {
- d = imap_make_flags(data->flags, flagstr);
+ if (msg->flags) {
+ d = imap_make_flags(msg->flags, flagstr);
flagstr[d++] = ' ';
}
flagstr[d] = 0;
@@ -1337,75 +1339,46 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data)
return DRV_OK;
}
-static void encode_html_chars(struct strbuf *p)
-{
- int i;
- for (i = 0; i < p->len; i++) {
- if (p->buf[i] == '&')
- strbuf_splice(p, i, 1, "&amp;", 5);
- if (p->buf[i] == '<')
- strbuf_splice(p, i, 1, "&lt;", 4);
- if (p->buf[i] == '>')
- strbuf_splice(p, i, 1, "&gt;", 4);
- if (p->buf[i] == '"')
- strbuf_splice(p, i, 1, "&quot;", 6);
- }
-}
-static void wrap_in_html(struct msg_data *msg)
+static void wrap_in_html(struct strbuf *msg)
{
struct strbuf buf = STRBUF_INIT;
- struct strbuf **lines;
- struct strbuf **p;
static char *content_type = "Content-Type: text/html;\n";
static char *pre_open = "<pre>\n";
static char *pre_close = "</pre>\n";
- int added_header = 0;
-
- strbuf_attach(&buf, msg->data, msg->len, msg->len);
- lines = strbuf_split(&buf, '\n');
- strbuf_release(&buf);
- for (p = lines; *p; p++) {
- if (! added_header) {
- if ((*p)->len == 1 && *((*p)->buf) == '\n') {
- strbuf_addstr(&buf, content_type);
- strbuf_addbuf(&buf, *p);
- strbuf_addstr(&buf, pre_open);
- added_header = 1;
- continue;
- }
- }
- else
- encode_html_chars(*p);
- strbuf_addbuf(&buf, *p);
- }
+ const char *body = strstr(msg->buf, "\n\n");
+
+ if (!body)
+ return; /* Headers but no body; no wrapping needed */
+
+ body += 2;
+
+ strbuf_add(&buf, msg->buf, body - msg->buf - 1);
+ strbuf_addstr(&buf, content_type);
+ strbuf_addch(&buf, '\n');
+ strbuf_addstr(&buf, pre_open);
+ strbuf_addstr_xml_quoted(&buf, body);
strbuf_addstr(&buf, pre_close);
- strbuf_list_free(lines);
- msg->len = buf.len;
- msg->data = strbuf_detach(&buf, NULL);
+
+ strbuf_release(msg);
+ *msg = buf;
}
#define CHUNKSIZE 0x1000
-static int read_message(FILE *f, struct msg_data *msg)
+static int read_message(FILE *f, struct strbuf *all_msgs)
{
- struct strbuf buf = STRBUF_INIT;
-
- memset(msg, 0, sizeof(*msg));
-
do {
- if (strbuf_fread(&buf, CHUNKSIZE, f) <= 0)
+ if (strbuf_fread(all_msgs, CHUNKSIZE, f) <= 0)
break;
} while (!feof(f));
- msg->len = buf.len;
- msg->data = strbuf_detach(&buf, NULL);
- return msg->len;
+ return ferror(f) ? -1 : 0;
}
-static int count_messages(struct msg_data *msg)
+static int count_messages(struct strbuf *all_msgs)
{
int count = 0;
- char *p = msg->data;
+ char *p = all_msgs->buf;
while (1) {
if (!prefixcmp(p, "From ")) {
@@ -1426,34 +1399,39 @@ static int count_messages(struct msg_data *msg)
return count;
}
-static int split_msg(struct msg_data *all_msgs, struct msg_data *msg, int *ofs)
+/*
+ * Copy the next message from all_msgs, starting at offset *ofs, to
+ * msg. Update *ofs to the start of the following message. Return
+ * true iff a message was successfully copied.
+ */
+static int split_msg(struct strbuf *all_msgs, struct strbuf *msg, int *ofs)
{
char *p, *data;
+ size_t len;
- memset(msg, 0, sizeof *msg);
if (*ofs >= all_msgs->len)
return 0;
- data = &all_msgs->data[*ofs];
- msg->len = all_msgs->len - *ofs;
+ data = &all_msgs->buf[*ofs];
+ len = all_msgs->len - *ofs;
- if (msg->len < 5 || prefixcmp(data, "From "))
+ if (len < 5 || prefixcmp(data, "From "))
return 0;
p = strchr(data, '\n');
if (p) {
- p = &p[1];
- msg->len -= p-data;
- *ofs += p-data;
+ p++;
+ len -= p - data;
+ *ofs += p - data;
data = p;
}
p = strstr(data, "\nFrom ");
if (p)
- msg->len = &p[1] - data;
+ len = &p[1] - data;
- msg->data = xmemdupz(data, msg->len);
- *ofs += msg->len;
+ strbuf_add(msg, data, len);
+ *ofs += len;
return 1;
}
@@ -1504,7 +1482,8 @@ static int git_imap_config(const char *key, const char *val, void *cb)
int main(int argc, char **argv)
{
- struct msg_data all_msgs, msg;
+ struct strbuf all_msgs = STRBUF_INIT;
+ struct msg_data msg = {STRBUF_INIT, 0};
struct store *ctx = NULL;
int ofs = 0;
int r;
@@ -1537,7 +1516,12 @@ int main(int argc, char **argv)
}
/* read the messages */
- if (!read_message(stdin, &all_msgs)) {
+ if (read_message(stdin, &all_msgs)) {
+ fprintf(stderr, "error reading input\n");
+ return 1;
+ }
+
+ if (all_msgs.len == 0) {
fprintf(stderr, "nothing to send\n");
return 1;
}
@@ -1559,11 +1543,12 @@ int main(int argc, char **argv)
ctx->name = imap_folder;
while (1) {
unsigned percent = n * 100 / total;
+
fprintf(stderr, "%4u%% (%d/%d) done\r", percent, n, total);
- if (!split_msg(&all_msgs, &msg, &ofs))
+ if (!split_msg(&all_msgs, &msg.data, &ofs))
break;
if (server.use_html)
- wrap_in_html(&msg);
+ wrap_in_html(&msg.data);
r = imap_store_msg(ctx, &msg);
if (r != DRV_OK)
break;
diff --git a/log-tree.c b/log-tree.c
index 4f86defe32..8876c736d4 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -671,6 +671,7 @@ void show_log(struct rev_info *opt)
ctx.preserve_subject = opt->preserve_subject;
ctx.reflog_info = opt->reflog_info;
ctx.fmt = opt->commit_format;
+ ctx.color = opt->diffopt.use_color;
pretty_print_commit(&ctx, commit, &msgbuf);
if (opt->add_signoff)
diff --git a/mailmap.c b/mailmap.c
index ea4b471ede..b16542febe 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -10,6 +10,7 @@ static inline void debug_mm(const char *format, ...) {}
#endif
const char *git_mailmap_file;
+const char *git_mailmap_blob;
struct mailmap_info {
char *name;
@@ -129,54 +130,119 @@ static char *parse_name_and_email(char *buffer, char **name,
return (*right == '\0' ? NULL : right);
}
-static int read_single_mailmap(struct string_list *map, const char *filename, char **repo_abbrev)
+static void read_mailmap_line(struct string_list *map, char *buffer,
+ char **repo_abbrev)
+{
+ char *name1 = NULL, *email1 = NULL, *name2 = NULL, *email2 = NULL;
+ if (buffer[0] == '#') {
+ static const char abbrev[] = "# repo-abbrev:";
+ int abblen = sizeof(abbrev) - 1;
+ int len = strlen(buffer);
+
+ if (!repo_abbrev)
+ return;
+
+ if (len && buffer[len - 1] == '\n')
+ buffer[--len] = 0;
+ if (!strncmp(buffer, abbrev, abblen)) {
+ char *cp;
+
+ if (repo_abbrev)
+ free(*repo_abbrev);
+ *repo_abbrev = xmalloc(len);
+
+ for (cp = buffer + abblen; isspace(*cp); cp++)
+ ; /* nothing */
+ strcpy(*repo_abbrev, cp);
+ }
+ return;
+ }
+ if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL)
+ parse_name_and_email(name2, &name2, &email2, 1);
+
+ if (email1)
+ add_mapping(map, name1, email1, name2, email2);
+}
+
+static int read_mailmap_file(struct string_list *map, const char *filename,
+ char **repo_abbrev)
{
char buffer[1024];
- FILE *f = (filename == NULL ? NULL : fopen(filename, "r"));
+ FILE *f;
- if (f == NULL)
- return 1;
- while (fgets(buffer, sizeof(buffer), f) != NULL) {
- char *name1 = NULL, *email1 = NULL, *name2 = NULL, *email2 = NULL;
- if (buffer[0] == '#') {
- static const char abbrev[] = "# repo-abbrev:";
- int abblen = sizeof(abbrev) - 1;
- int len = strlen(buffer);
-
- if (!repo_abbrev)
- continue;
-
- if (len && buffer[len - 1] == '\n')
- buffer[--len] = 0;
- if (!strncmp(buffer, abbrev, abblen)) {
- char *cp;
-
- if (repo_abbrev)
- free(*repo_abbrev);
- *repo_abbrev = xmalloc(len);
-
- for (cp = buffer + abblen; isspace(*cp); cp++)
- ; /* nothing */
- strcpy(*repo_abbrev, cp);
- }
- continue;
- }
- if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL)
- parse_name_and_email(name2, &name2, &email2, 1);
+ if (!filename)
+ return 0;
- if (email1)
- add_mapping(map, name1, email1, name2, email2);
+ f = fopen(filename, "r");
+ if (!f) {
+ if (errno == ENOENT)
+ return 0;
+ return error("unable to open mailmap at %s: %s",
+ filename, strerror(errno));
}
+
+ while (fgets(buffer, sizeof(buffer), f) != NULL)
+ read_mailmap_line(map, buffer, repo_abbrev);
fclose(f);
return 0;
}
+static void read_mailmap_buf(struct string_list *map,
+ const char *buf, unsigned long len,
+ char **repo_abbrev)
+{
+ while (len) {
+ const char *end = strchrnul(buf, '\n');
+ unsigned long linelen = end - buf + 1;
+ char *line = xmemdupz(buf, linelen);
+
+ read_mailmap_line(map, line, repo_abbrev);
+
+ free(line);
+ buf += linelen;
+ len -= linelen;
+ }
+}
+
+static int read_mailmap_blob(struct string_list *map,
+ const char *name,
+ char **repo_abbrev)
+{
+ unsigned char sha1[20];
+ char *buf;
+ unsigned long size;
+ enum object_type type;
+
+ if (!name)
+ return 0;
+ if (get_sha1(name, sha1) < 0)
+ return 0;
+
+ buf = read_sha1_file(sha1, &type, &size);
+ if (!buf)
+ return error("unable to read mailmap object at %s", name);
+ if (type != OBJ_BLOB)
+ return error("mailmap is not a blob: %s", name);
+
+ read_mailmap_buf(map, buf, size, repo_abbrev);
+
+ free(buf);
+ return 0;
+}
+
int read_mailmap(struct string_list *map, char **repo_abbrev)
{
+ int err = 0;
+
map->strdup_strings = 1;
- /* each failure returns 1, so >1 means both calls failed */
- return read_single_mailmap(map, ".mailmap", repo_abbrev) +
- read_single_mailmap(map, git_mailmap_file, repo_abbrev) > 1;
+
+ if (!git_mailmap_blob && is_bare_repository())
+ git_mailmap_blob = "HEAD:.mailmap";
+
+ err |= read_mailmap_file(map, ".mailmap", repo_abbrev);
+ err |= read_mailmap_blob(map, git_mailmap_blob, repo_abbrev);
+ err |= read_mailmap_file(map, git_mailmap_file, repo_abbrev);
+ return err;
}
void clear_mailmap(struct string_list *map)
diff --git a/parse-options.c b/parse-options.c
index c1c66bd408..67e98a6323 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -18,15 +18,6 @@ int optbug(const struct option *opt, const char *reason)
return error("BUG: switch '%c' %s", opt->short_name, reason);
}
-int opterror(const struct option *opt, const char *reason, int flags)
-{
- if (flags & OPT_SHORT)
- return error("switch `%c' %s", opt->short_name, reason);
- if (flags & OPT_UNSET)
- return error("option `no-%s' %s", opt->long_name, reason);
- return error("option `%s' %s", opt->long_name, reason);
-}
-
static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
int flags, const char **arg)
{
@@ -594,3 +585,12 @@ static int parse_options_usage(struct parse_opt_ctx_t *ctx,
return usage_with_options_internal(ctx, usagestr, opts, 0, err);
}
+#undef opterror
+int opterror(const struct option *opt, const char *reason, int flags)
+{
+ if (flags & OPT_SHORT)
+ return error("switch `%c' %s", opt->short_name, reason);
+ if (flags & OPT_UNSET)
+ return error("option `no-%s' %s", opt->long_name, reason);
+ return error("option `%s' %s", opt->long_name, reason);
+}
diff --git a/parse-options.h b/parse-options.h
index 71a39c60d9..e703853749 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -177,6 +177,10 @@ extern NORETURN void usage_msg_opt(const char *msg,
extern int optbug(const struct option *opt, const char *reason);
extern int opterror(const struct option *opt, const char *reason, int flags);
+#ifdef __GNUC__
+#define opterror(o,r,f) (opterror((o),(r),(f)), -1)
+#endif
+
/*----- incremental advanced APIs -----*/
enum {
diff --git a/po/de.po b/po/de.po
index 0e8ed5437a..c8ad2f01c9 100644
--- a/po/de.po
+++ b/po/de.po
@@ -33,10 +33,10 @@ msgid ""
"appropriate to mark resolution and make a commit,\n"
"or use 'git commit -a'."
msgstr ""
-"Korrigiere dies im Arbeitsbaum,\n"
-"und benutze dann 'git add/rm <Datei>'\n"
+"Korrigieren Sie dies im Arbeitsbaum,\n"
+"und benutzen Sie dann 'git add/rm <Datei>'\n"
"um die Auflösung entsprechend zu markieren und einzutragen,\n"
-"oder benutze 'git commit -a'."
+"oder benutzen Sie 'git commit -a'."
#: archive.c:10
msgid "git archive [options] <tree-ish> [<path>...]"
@@ -131,7 +131,7 @@ msgid ""
"Use '\\!' for literal leading exclamation."
msgstr ""
"Verneinende Muster sind in Git-Attributen verboten.\n"
-"Benutze '\\!' für führende Ausrufezeichen."
+"Benutzen Sie '\\!' für führende Ausrufezeichen."
#: bundle.c:36
#, c-format
@@ -381,7 +381,7 @@ msgstr "Vorhandene Git-Kommandos in '%s'"
#: help.c:219
msgid "git commands available from elsewhere on your $PATH"
-msgstr "Vorhandene Git-Kommandos irgendwo in deinem $PATH"
+msgstr "Vorhandene Git-Kommandos irgendwo in Ihrem $PATH"
#: help.c:275
#, c-format
@@ -394,7 +394,7 @@ msgstr ""
#: help.c:332
msgid "Uh oh. Your system reports no Git commands at all."
-msgstr "Uh oh. Keine Git-Kommandos auf deinem System vorhanden."
+msgstr "Uh oh. Keine Git-Kommandos auf Ihrem System vorhanden."
#: help.c:354
#, c-format
@@ -402,8 +402,8 @@ msgid ""
"WARNING: You called a Git command named '%s', which does not exist.\n"
"Continuing under the assumption that you meant '%s'"
msgstr ""
-"Warnung: Du hast das nicht existierende Git-Kommando '%s' ausgeführt.\n"
-"Setze fort unter der Annahme das du '%s' gemeint hast"
+"Warnung: Sie haben das nicht existierende Git-Kommando '%s' ausgeführt.\n"
+"Setze fort unter der Annahme, dass Sie '%s' gemeint haben"
#: help.c:359
#, c-format
@@ -424,10 +424,10 @@ msgid_plural ""
"Did you mean one of these?"
msgstr[0] ""
"\n"
-"Hast du das gemeint?"
+"Haben Sie das gemeint?"
msgstr[1] ""
"\n"
-"Hast du eines von diesen gemeint?"
+"Haben Sie eines von diesen gemeint?"
#: merge.c:56
msgid "failed to read the cache"
@@ -721,12 +721,12 @@ msgstr " %s"
#, c-format
msgid "Your branch is ahead of '%s' by %d commit.\n"
msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
-msgstr[0] "Dein Zweig ist vor '%s' um %d Version.\n"
-msgstr[1] "Dein Zweig ist vor '%s' um %d Versionen.\n"
+msgstr[0] "Ihr Zweig ist vor '%s' um %d Version.\n"
+msgstr[1] "Ihr Zweig ist vor '%s' um %d Versionen.\n"
#: remote.c:1637
msgid " (use \"git push\" to publish your local commits)\n"
-msgstr " (benutze \"git push\" um deine lokalen Versionen herauszubringen)\n"
+msgstr " (benutzen Sie \"git push\" um lokalen Versionen herauszubringen)\n"
#: remote.c:1640
#, c-format
@@ -734,15 +734,15 @@ msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
msgid_plural ""
"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
msgstr[0] ""
-"Dein Zweig ist zu '%s' um %d Version hinterher, und kann vorgespult werden.\n"
+"Ihr Zweig ist zu '%s' um %d Version hinterher, und kann vorgespult werden.\n"
msgstr[1] ""
-"Dein Zweig ist zu '%s' um %d Versionen hinterher, und kann vorgespult "
+"Ihr Zweig ist zu '%s' um %d Versionen hinterher, und kann vorgespult "
"werden.\n"
#: remote.c:1647
msgid " (use \"git pull\" to update your local branch)\n"
msgstr ""
-" (benutze \"git pull\" um deinen lokalen Zweig zu aktualisieren)\n"
+" (benutzen Sie \"git pull\" um Ihren lokalen Zweig zu aktualisieren)\n"
#: remote.c:1650
#, c-format
@@ -753,16 +753,16 @@ msgid_plural ""
"Your branch and '%s' have diverged,\n"
"and have %d and %d different commits each, respectively.\n"
msgstr[0] ""
-"Dein Zweig und '%s' sind divergiert,\n"
+"Ihr Zweig und '%s' sind divergiert,\n"
"und haben jeweils %d und %d unterschiedliche Versionen.\n"
msgstr[1] ""
-"Dein Zweig und '%s' sind divergiert,\n"
+"Ihr Zweig und '%s' sind divergiert,\n"
"und haben jeweils %d und %d unterschiedliche Versionen.\n"
#: remote.c:1659
msgid " (use \"git pull\" to merge the remote branch into yours)\n"
msgstr ""
-" (benutze \"git pull\" um deinen Zweig mit dem externen zusammenzuführen)\n"
+" (benutzen Sie \"git pull\" um Ihren Zweig mit dem externen zusammenzuführen)\n"
#: sequencer.c:123 builtin/merge.c:761 builtin/merge.c:874 builtin/merge.c:984
#: builtin/merge.c:994
@@ -781,7 +781,7 @@ msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
-"nach Auflösung der Konflikte, markiere die korrigierten Pfade\n"
+"nach Auflösung der Konflikte, markieren Sie die korrigierten Pfade\n"
"mit 'git add <Pfade>' oder 'git rm <Pfade>'"
#: sequencer.c:149
@@ -790,9 +790,9 @@ msgid ""
"with 'git add <paths>' or 'git rm <paths>'\n"
"and commit the result with 'git commit'"
msgstr ""
-"nach Auflösung der Konflikte, markiere die korrigierten Pfade\n"
-"mit 'git add <Pfade>' oder 'git rm <Pfade>'und trage das Ergebnis ein mit "
-"'git commit'"
+"nach Auflösung der Konflikte, markieren Sie die korrigierten Pfade\n"
+"mit 'git add <Pfade>' oder 'git rm <Pfade>'und tragen Sie das Ergebnis mit\n"
+"'git commit' ein"
#: sequencer.c:162 sequencer.c:770 sequencer.c:853
#, c-format
@@ -807,15 +807,15 @@ msgstr "Fehler bei Nachbereitung von %s"
#: sequencer.c:180
msgid "Your local changes would be overwritten by cherry-pick."
msgstr ""
-"Deine lokalen Änderungen würden von \"cherry-pick\" überschrieben werden."
+"Ihre lokalen Änderungen würden von \"cherry-pick\" überschrieben werden."
#: sequencer.c:182
msgid "Your local changes would be overwritten by revert."
-msgstr "Deine lokalen Änderungen würden von \"revert\" überschrieben werden."
+msgstr "Ihre lokalen Änderungen würden von \"revert\" überschrieben werden."
#: sequencer.c:185
msgid "Commit your changes or stash them to proceed."
-msgstr "Trage deine Änderungen ein oder benutze \"stash\" um fortzufahren."
+msgstr "Tragen Sie Ihre Änderungen ein oder benutzen Sie \"stash\" um fortzufahren."
#. TRANSLATORS: %s will be "revert" or "cherry-pick"
#: sequencer.c:235
@@ -843,11 +843,11 @@ msgstr "Konnte Elternversion %s nicht parsen\n"
#: sequencer.c:403
msgid "Your index file is unmerged."
-msgstr "Deine Bereitstellungsdatei ist nicht zusammengeführt."
+msgstr "Ihre Bereitstellungsdatei ist nicht zusammengeführt."
#: sequencer.c:406
msgid "You do not have a valid HEAD"
-msgstr "Du hast keine gültige Zweigspitze (HEAD)"
+msgstr "Sie haben keine gültige Zweigspitze (HEAD)"
#: sequencer.c:421
#, c-format
@@ -953,7 +953,7 @@ msgstr "\"cherry-pick\" oder \"revert\" ist bereits im Gang"
#: sequencer.c:752
msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
-msgstr "versuche \"git cherry-pick (--continue | --quit | --abort)\""
+msgstr "versuchen Sie \"git cherry-pick (--continue | --quit | --abort)\""
#: sequencer.c:756
#, c-format
@@ -1053,28 +1053,28 @@ msgstr "Nicht zusammengeführte Pfade:"
#, c-format
msgid " (use \"git reset %s <file>...\" to unstage)"
msgstr ""
-" (benutze \"git reset %s <Datei>...\" zum Herausnehmen aus der "
+" (benutzen Sie \"git reset %s <Datei>...\" zum Herausnehmen aus der "
"Bereitstellung)"
#: wt-status.c:169 wt-status.c:196
msgid " (use \"git rm --cached <file>...\" to unstage)"
msgstr ""
-" (benutze \"git rm --cached <Datei>...\" zum Herausnehmen aus der "
+" (benutzen Sie \"git rm --cached <Datei>...\" zum Herausnehmen aus der "
"Bereitstellung)"
#: wt-status.c:173
msgid " (use \"git add <file>...\" to mark resolution)"
-msgstr " (benutze \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
+msgstr " (benutzen Sie \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
#: wt-status.c:175 wt-status.c:179
msgid " (use \"git add/rm <file>...\" as appropriate to mark resolution)"
msgstr ""
-" (benutze \"git add/rm <Datei>...\" um die Auflösung entsprechend zu "
+" (benutzen Sie \"git add/rm <Datei>...\" um die Auflösung entsprechend zu "
"markieren)"
#: wt-status.c:177
msgid " (use \"git rm <file>...\" to mark resolution)"
-msgstr " (benutze \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
+msgstr " (benutzen Sie \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
#: wt-status.c:188
msgid "Changes to be committed:"
@@ -1086,29 +1086,29 @@ msgstr "Änderungen, die nicht zum Eintragen bereitgestellt sind:"
#: wt-status.c:210
msgid " (use \"git add <file>...\" to update what will be committed)"
-msgstr " (benutze \"git add <Datei>...\" zum Bereitstellen)"
+msgstr " (benutzen Sie \"git add <Datei>...\" zum Bereitstellen)"
#: wt-status.c:212
msgid " (use \"git add/rm <file>...\" to update what will be committed)"
-msgstr " (benutze \"git add/rm <Datei>...\" zum Bereitstellen)"
+msgstr " (benutzen Sie \"git add/rm <Datei>...\" zum Bereitstellen)"
#: wt-status.c:213
msgid ""
" (use \"git checkout -- <file>...\" to discard changes in working directory)"
msgstr ""
-" (benutze \"git checkout -- <Datei>...\" um die Änderungen im "
+" (benutzen Sie \"git checkout -- <Datei>...\" um die Änderungen im "
"Arbeitsverzeichnis zu verwerfen)"
#: wt-status.c:215
msgid " (commit or discard the untracked or modified content in submodules)"
msgstr ""
-" (trage ein oder verwerfe den unbeobachteten oder geänderten Inhalt in den "
+" (tragen Sie ein oder verwerfen Sie den unbeobachteten oder geänderten Inhalt in den "
"Unterprojekten)"
#: wt-status.c:227
#, c-format
msgid " (use \"git %s <file>...\" to include in what will be committed)"
-msgstr " (benutze \"git %s <Datei>...\" zum Einfügen in die Eintragung)"
+msgstr " (benutzen Sie \"git %s <Datei>...\" zum Einfügen in die Eintragung)"
#: wt-status.c:244
msgid "bug"
@@ -1201,20 +1201,20 @@ msgstr "Fehler: unbehandelter Differenz-Status %c"
#: wt-status.c:785
msgid "You have unmerged paths."
-msgstr "Du hast nicht zusammengeführte Pfade."
+msgstr "Sie haben nicht zusammengeführte Pfade."
#: wt-status.c:788 wt-status.c:912
msgid " (fix conflicts and run \"git commit\")"
-msgstr " (behebe die Konflikte und führe \"git commit\" aus)"
+msgstr " (beheben Sie die Konflikte und führen Sie \"git commit\" aus)"
#: wt-status.c:791
msgid "All conflicts fixed but you are still merging."
msgstr ""
-"Alle Konflikte sind behoben, aber du bist immer noch beim Zusammenführen."
+"Alle Konflikte sind behoben, aber Sie sind immer noch beim Zusammenführen."
#: wt-status.c:794
msgid " (use \"git commit\" to conclude merge)"
-msgstr " (benutze \"git commit\" um die Zusammenführung abzuschließen)"
+msgstr " (benutzen Sie \"git commit\" um die Zusammenführung abzuschließen)"
#: wt-status.c:804
msgid "You are in the middle of an am session."
@@ -1226,80 +1226,80 @@ msgstr "Der aktuelle Patch ist leer."
#: wt-status.c:811
msgid " (fix conflicts and then run \"git am --resolved\")"
-msgstr " (behebe die Konflikte und führe dann \"git am --resolved\" aus)"
+msgstr " (beheben Sie die Konflikte und führen Sie dann \"git am --resolved\" aus)"
#: wt-status.c:813
msgid " (use \"git am --skip\" to skip this patch)"
-msgstr " (benutze \"git am --skip\" um diesen Patch auszulassen)"
+msgstr " (benutzen Sie \"git am --skip\" um diesen Patch auszulassen)"
#: wt-status.c:815
msgid " (use \"git am --abort\" to restore the original branch)"
msgstr ""
-" (benutze \"git am --abort\" um den ursprünglichen Zweig wiederherzustellen)"
+" (benutzen Sie \"git am --abort\" um den ursprünglichen Zweig wiederherzustellen)"
#: wt-status.c:873 wt-status.c:883
msgid "You are currently rebasing."
-msgstr "Du bist gerade beim Neuaufbau."
+msgstr "Sie sind gerade beim Neuaufbau."
#: wt-status.c:876
msgid " (fix conflicts and then run \"git rebase --continue\")"
-msgstr " (behebe die Konflikte und führe dann \"git rebase --continue\" aus)"
+msgstr " (beheben Sie die Konflikte und führen Sie dann \"git rebase --continue\" aus)"
#: wt-status.c:878
msgid " (use \"git rebase --skip\" to skip this patch)"
-msgstr " (benutze \"git rebase --skip\" um diesen Patch auszulassen)"
+msgstr " (benutzen Sie \"git rebase --skip\" um diesen Patch auszulassen)"
#: wt-status.c:880
msgid " (use \"git rebase --abort\" to check out the original branch)"
msgstr ""
-" (benutze \"git rebase --abort\" um den ursprünglichen Zweig auszuchecken)"
+" (benutzen Sie \"git rebase --abort\" um den ursprünglichen Zweig auszuchecken)"
#: wt-status.c:886
msgid " (all conflicts fixed: run \"git rebase --continue\")"
-msgstr " (alle Konflikte behoben: führe \"git rebase --continue\" aus)"
+msgstr " (alle Konflikte behoben: führen Sie \"git rebase --continue\" aus)"
#: wt-status.c:888
msgid "You are currently splitting a commit during a rebase."
-msgstr "Du teilst gerade eine Version während eines Neuaufbaus auf."
+msgstr "Sie teilen gerade eine Version während eines Neuaufbaus auf."
#: wt-status.c:891
msgid " (Once your working directory is clean, run \"git rebase --continue\")"
msgstr ""
-" (Sobald dein Arbeitsverzeichnis sauber ist, führe \"git rebase --continue"
+" (Sobald Ihr Arbeitsverzeichnis sauber ist, führen Sie \"git rebase --continue"
"\" aus)"
#: wt-status.c:893
msgid "You are currently editing a commit during a rebase."
-msgstr "Du editierst gerade eine Version während eines Neuaufbaus."
+msgstr "Sie editieren gerade eine Version während eines Neuaufbaus."
#: wt-status.c:896
msgid " (use \"git commit --amend\" to amend the current commit)"
msgstr ""
-" (benutze \"git commit --amend\" um die aktuelle Version nachzubessern)"
+" (benutzen Sie \"git commit --amend\" um die aktuelle Version nachzubessern)"
#: wt-status.c:898
msgid ""
" (use \"git rebase --continue\" once you are satisfied with your changes)"
msgstr ""
-" (benutze \"git rebase --continue\" sobald deine Änderungen abgeschlossen "
+" (benutzen Sie \"git rebase --continue\" sobald Ihre Änderungen abgeschlossen "
"sind)"
#: wt-status.c:908
msgid "You are currently cherry-picking."
-msgstr "Du führst gerade \"cherry-pick\" aus."
+msgstr "Sie führen gerade \"cherry-pick\" aus."
#: wt-status.c:915
msgid " (all conflicts fixed: run \"git commit\")"
-msgstr " (alle Konflikte behoben: führe \"git commit\" aus)"
+msgstr " (alle Konflikte behoben: führen Sie \"git commit\" aus)"
#: wt-status.c:924
msgid "You are currently bisecting."
-msgstr "Du bist gerade beim Halbieren."
+msgstr "Sie sind gerade beim Halbieren."
#: wt-status.c:927
msgid " (use \"git bisect reset\" to get back to the original branch)"
msgstr ""
-" (benutze \"git bisect reset\" um zum ursprünglichen Zweig zurückzukehren)"
+" (benutzen Sie \"git bisect reset\" um zum ursprünglichen Zweig zurückzukehren)"
#: wt-status.c:978
msgid "On branch "
@@ -1328,7 +1328,7 @@ msgstr "Unbeobachtete Dateien nicht aufgelistet%s"
#: wt-status.c:1017
msgid " (use -u option to show untracked files)"
-msgstr " (benutze die Option -u um unbeobachteten Dateien anzuzeigen)"
+msgstr " (benutzen Sie die Option -u um unbeobachteten Dateien anzuzeigen)"
#: wt-status.c:1023
msgid "No changes"
@@ -1338,7 +1338,7 @@ msgstr "Keine Änderungen"
#, c-format
msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
msgstr ""
-"keine Änderungen zum Eintragen hinzugefügt (benutze \"git add\" und/oder "
+"keine Änderungen zum Eintragen hinzugefügt (benutzen Sie \"git add\" und/oder "
"\"git commit -a\")\n"
#: wt-status.c:1031
@@ -1353,7 +1353,7 @@ msgid ""
"track)\n"
msgstr ""
"nichts zum Eintragen hinzugefügt, aber es gibt unbeobachtete Dateien "
-"(benutze \"git add\" zum Beobachten)\n"
+"(benutzen Sie \"git add\" zum Beobachten)\n"
#: wt-status.c:1037
#, c-format
@@ -1364,8 +1364,8 @@ msgstr "nichts zum Eintragen hinzugefügt, aber es gibt unbeobachtete Dateien\n"
#, c-format
msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
msgstr ""
-"nichts einzutragen (Erstelle/Kopiere Dateien und benutze \"git add\" zum "
-"Beobachten)\n"
+"nichts einzutragen (Erstellen/Kopieren Sie Dateien und benutzen Sie \"git add\" "
+"zum Beobachten)\n"
#: wt-status.c:1043 wt-status.c:1048
#, c-format
@@ -1376,7 +1376,7 @@ msgstr "nichts einzutragen\n"
#, c-format
msgid "nothing to commit (use -u to show untracked files)\n"
msgstr ""
-"nichts einzutragen (benutze die Option -u, um unbeobachtete Dateien "
+"nichts einzutragen (benutzen Sie die Option -u, um unbeobachtete Dateien "
"anzuzeigen)\n"
#: wt-status.c:1050
@@ -1477,7 +1477,7 @@ msgstr "Konnte '%s' nicht anwenden."
#: builtin/add.c:313
msgid "The following paths are ignored by one of your .gitignore files:\n"
msgstr ""
-"Die folgenden Pfade werden durch eine deiner \".gitignore\" Dateien "
+"Die folgenden Pfade werden durch eine Ihrer \".gitignore\" Dateien "
"ignoriert:\n"
#: builtin/add.c:319 builtin/clean.c:52 builtin/fetch.c:78 builtin/mv.c:63
@@ -1538,7 +1538,7 @@ msgstr "prüft ob - auch fehlende - Dateien im Probelauf ignoriert werden"
#: builtin/add.c:353
#, c-format
msgid "Use -f if you really want to add them.\n"
-msgstr "Verwende -f wenn du diese wirklich hinzufügen möchtest.\n"
+msgstr "Verwenden Sie -f wenn Sie diese wirklich hinzufügen möchten.\n"
#: builtin/add.c:354
msgid "no files added"
@@ -1565,7 +1565,7 @@ msgstr "Nichts spezifiziert, nichts hinzugefügt.\n"
#: builtin/add.c:415
#, c-format
msgid "Maybe you wanted to say 'git add .'?\n"
-msgstr "Wolltest du vielleicht 'git add .' sagen?\n"
+msgstr "Wollten Sie vielleicht 'git add .' sagen?\n"
#: builtin/add.c:421 builtin/clean.c:95 builtin/commit.c:291 builtin/mv.c:82
#: builtin/rm.c:235
@@ -2269,7 +2269,7 @@ msgid ""
"If you are sure you want to delete it, run 'git branch -D %s'."
msgstr ""
"Der Zweig '%s' ist nicht vollständig zusammengeführt.\n"
-"Wenn du sicher bist diesen Zweig zu entfernen, führe 'git branch -D %s' aus."
+"Wenn Sie sicher sind diesen Zweig zu entfernen, führen Sie 'git branch -D %s' aus."
#: builtin/branch.c:180
msgid "Update of config-file failed"
@@ -2287,7 +2287,7 @@ msgstr "Konnte Versionsobjekt für Zweigspitze (HEAD) nicht nachschlagen."
#, c-format
msgid "Cannot delete the branch '%s' which you are currently on."
msgstr ""
-"Kann Zweig '%s' nicht entfernen, da du dich gerade auf diesem befindest."
+"Kann Zweig '%s' nicht entfernen, da Sie sich gerade auf diesem befinden."
#: builtin/branch.c:235
#, c-format
@@ -2365,7 +2365,7 @@ msgstr "Konnte einige Referenzen nicht lesen"
#: builtin/branch.c:638
msgid "cannot rename the current branch while not on any."
msgstr ""
-"Kann aktuellen Zweig nicht umbenennen, solange du dich auf keinem befindest."
+"Kann aktuellen Zweig nicht umbenennen, solange Sie sich auf keinem befinden."
#: builtin/branch.c:648
#, c-format
@@ -2527,8 +2527,8 @@ msgid ""
"The --set-upstream flag is deprecated and will be removed. Consider using --"
"track or --set-upstream-to\n"
msgstr ""
-"Die --set-upstream Option ist veraltet und wird entfernt. Benutze --track "
-"oder --set-upstream-to\n"
+"Die --set-upstream Option ist veraltet und wird entfernt. Benutzen Sie "
+"--track oder --set-upstream-to\n"
#: builtin/branch.c:934
#, c-format
@@ -2538,8 +2538,8 @@ msgid ""
"\n"
msgstr ""
"\n"
-"Wenn du wolltest, dass '%s' den Zweig '%s' als externen Ãœbernahmezweig hat, "
-"führe aus:\n"
+"Wenn Sie wollten, dass '%s' den Zweig '%s' als externen Ãœbernahmezweig hat, "
+"führen Sie aus:\n"
#: builtin/branch.c:935
#, c-format
@@ -2743,7 +2743,7 @@ msgstr "Pfad '%s' ist nicht zusammengeführt."
#: builtin/checkout.c:448
msgid "you need to resolve your current index first"
-msgstr "Du musst zuerst deine aktuelle Bereitstellung auflösen."
+msgstr "Sie müssen zuerst Ihre aktuelle Bereitstellung auflösen."
#: builtin/checkout.c:569
#, c-format
@@ -2798,13 +2798,13 @@ msgid_plural ""
"\n"
"%s\n"
msgstr[0] ""
-"Warnung: Du bist um %d Version hinterher, nicht verbunden zu\n"
-"einem deiner Zweige:\n"
+"Warnung: Sie sind um %d Version hinterher, nicht verbunden zu\n"
+"einem Ihrer Zweige:\n"
"\n"
"%s\n"
msgstr[1] ""
-"Warnung: Du bist um %d Versionen hinterher, nicht verbunden zu\n"
-"einem deiner Zweige:\n"
+"Warnung: Sie sind um %d Versionen hinterher, nicht verbunden zu\n"
+"einem Ihrer Zweige:\n"
"\n"
"%s\n"
@@ -2817,7 +2817,7 @@ msgid ""
" git branch new_branch_name %s\n"
"\n"
msgstr ""
-"Wenn du diese durch einen neuen Zweig behalten möchtest, dann könnte jetzt\n"
+"Wenn Sie diese durch einen neuen Zweig behalten möchten, dann könnte jetzt\n"
"ein guter Zeitpunkt sein dies zu tun mit:\n"
"\n"
" git branch neuer_zweig_name %s\n"
@@ -2833,7 +2833,7 @@ msgstr "Vorherige Position der Zweigspitze (HEAD) war"
#: builtin/checkout.c:761 builtin/checkout.c:950
msgid "You are on a branch yet to be born"
-msgstr "du bist auf einem Zweig, der noch geboren wird"
+msgstr "Sie sind auf einem Zweig, der noch geboren wird"
#. case (1)
#: builtin/checkout.c:886
@@ -2946,7 +2946,7 @@ msgstr "--track benötigt einen Zweignamen"
#: builtin/checkout.c:1081
msgid "Missing branch name; try -b"
-msgstr "Vermisse Zweignamen; versuche -b"
+msgstr "Vermisse Zweignamen; versuchen Sie -b"
#: builtin/checkout.c:1116
msgid "invalid path specification"
@@ -2959,7 +2959,7 @@ msgid ""
"Did you intend to checkout '%s' which can not be resolved as commit?"
msgstr ""
"Kann nicht gleichzeitig Pfade aktualisieren und zu Zweig '%s' wechseln.\n"
-"Hast du beabsichtigt '%s' auszuchecken, welcher nicht als Version aufgelöst "
+"Haben Sie beabsichtigt '%s' auszuchecken, welcher nicht als Version aufgelöst "
"werden kann?"
#: builtin/checkout.c:1128
@@ -2973,7 +2973,7 @@ msgid ""
"checking out of the index."
msgstr ""
"git checkout: --ours/--theirs, --force und --merge sind inkompatibel wenn\n"
-"du aus der Bereitstellung auscheckst."
+"Sie aus der Bereitstellung auschecken."
#: builtin/clean.c:19
msgid "git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
@@ -3203,7 +3203,7 @@ msgstr "Zu viele Argumente."
#: builtin/clone.c:694
msgid "You must specify a repository to clone."
-msgstr "Du musst ein Projektarchiv zum Klonen angeben."
+msgstr "Sie müssen ein Projektarchiv zum Klonen angeben."
#: builtin/clone.c:705
#, c-format
@@ -3217,7 +3217,7 @@ msgstr "Projektarchiv '%s' existiert nicht."
#: builtin/clone.c:724
msgid "--depth is ignored in local clones; use file:// instead."
-msgstr "--depth wird in lokalen Klonen ignoriert; benutze stattdessen file://."
+msgstr "--depth wird in lokalen Klonen ignoriert; benutzen Sie stattdessen file://."
#: builtin/clone.c:734
#, c-format
@@ -3261,7 +3261,7 @@ msgstr "externer Zweig %s nicht im anderen Projektarchiv %s gefunden"
#: builtin/clone.c:879
msgid "You appear to have cloned an empty repository."
-msgstr "Du scheinst ein leeres Projektarchiv geklont zu haben."
+msgstr "Sie scheinen ein leeres Projektarchiv geklont zu haben."
#: builtin/column.c:9
msgid "git column [options]"
@@ -3316,15 +3316,15 @@ msgid ""
"\n"
" git commit --amend --reset-author\n"
msgstr ""
-"Dein Name und E-Mail Adresse wurden automatisch auf Basis\n"
-"deines Benutzer- und Rechnernamens konfiguriert. Bitte prüfe, dass diese\n"
-"zutreffend sind. Du kannst diese Meldung unterdrücken, indem du diese\n"
-"explizit setzt:\n"
+"Ihr Name und E-Mail Adresse wurden automatisch auf Basis\n"
+"Ihres Benutzer- und Rechnernamens konfiguriert. Bitte prüfen Sie, dass\n"
+"diese zutreffend sind. Sie können diese Meldung unterdrücken, indem Sie\n"
+"diese explizit setzen:\n"
"\n"
-" git config --global user.name \"Dein Name\"\n"
-" git config --global user.email deine@emailadresse.de\n"
+" git config --global user.name \"Ihr Name\"\n"
+" git config --global user.email ihre@emailadresse.de\n"
"\n"
-"Nachdem du das getan hast, kannst du deine Identität für diese Version "
+"Nachdem Sie das getan hast, können Sie Ihre Identität für diese Version "
"ändern mit:\n"
"\n"
" git commit --amend --reset-author\n"
@@ -3335,8 +3335,8 @@ msgid ""
"it empty. You can repeat your command with --allow-empty, or you can\n"
"remove the commit entirely with \"git reset HEAD^\".\n"
msgstr ""
-"Du fragtest die jüngste Version nachzubessern, aber das würde diese leer\n"
-"machen. Du kannst Dein Kommando mit --allow-empty wiederholen, oder die\n"
+"Sie fragten die jüngste Version nachzubessern, aber das würde diese leer\n"
+"machen. Sie können Ihr Kommando mit --allow-empty wiederholen, oder die\n"
"Version mit \"git reset HEAD^\" vollständig entfernen.\n"
#: builtin/commit.c:61
@@ -3350,11 +3350,11 @@ msgid ""
msgstr ""
"Der letzte \"cherry-pick\" ist jetzt leer, möglicherweise durch eine "
"Konfliktauflösung.\n"
-"Wenn du dies trotzdem eintragen willst, benutze:\n"
+"Wenn Sie dies trotzdem eintragen wollen, benutzen Sie:\n"
"\n"
" git commit --allow-empty\n"
"\n"
-"Andernfalls benutze bitte 'git reset'\n"
+"Andernfalls benutzen Sie bitte 'git reset'\n"
#: builtin/commit.c:258
msgid "failed to unpack HEAD tree object"
@@ -3456,10 +3456,10 @@ msgid ""
"and try again.\n"
msgstr ""
"\n"
-"Es sieht so aus, als trägst du eine Zusammenführung ein.\n"
-"Falls das nicht korrekt ist, lösche bitte die Datei\n"
+"Es sieht so aus, als tragen Sie eine Zusammenführung ein.\n"
+"Falls das nicht korrekt ist, löschen Sie bitte die Datei\n"
"\t%s\n"
-"und versuche es erneut.\n"
+"und versuchen Sie es erneut.\n"
#: builtin/commit.c:723
#, c-format
@@ -3471,17 +3471,17 @@ msgid ""
"and try again.\n"
msgstr ""
"\n"
-"Es sieht so aus, als trägst du ein \"cherry-pick\" ein.\n"
-"Falls das nicht korrekt ist, lösche bitte die Datei\n"
+"Es sieht so aus, als tragen Sie ein \"cherry-pick\" ein.\n"
+"Falls das nicht korrekt ist, löschen Sie bitte die Datei\n"
"\t%s\n"
-"und versuche es erneut.\n"
+"und versuchen Sie es erneut.\n"
#: builtin/commit.c:735
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
"with '#' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
-"Bitte gebe eine Versionsbeschreibung für deine Änderungen ein. Zeilen,\n"
+"Bitte geben Sie eine Versionsbeschreibung für Ihre Änderungen ein. Zeilen,\n"
"die mit '#' beginnen, werden ignoriert, und eine leere Versionsbeschreibung\n"
"bricht die Eintragung ab.\n"
@@ -3491,8 +3491,8 @@ msgid ""
"with '#' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
-"Bitte gebe eine Versionsbeschreibung für deine Änderungen ein. Zeilen, die\n"
-"mit '#' beginnen, werden beibehalten; wenn du möchtest, kannst du diese "
+"Bitte geben Sie eine Versionsbeschreibung für Ihre Änderungen ein. Zeilen, die\n"
+"mit '#' beginnen, werden beibehalten; wenn Sie möchten, können Sie diese "
"entfernen.\n"
"Eine leere Versionsbeschreibung bricht die Eintragung ab.\n"
@@ -3535,7 +3535,7 @@ msgstr "Verwendung von --reset-author und --author macht keinen Sinn."
#: builtin/commit.c:995
msgid "You have nothing to amend."
-msgstr "Du hast nichts zum nachbessern."
+msgstr "Sie haben nichts zum nachbessern."
#: builtin/commit.c:998
msgid "You are in the middle of a merge -- cannot amend."
@@ -3726,7 +3726,7 @@ msgstr ""
#: builtin/commit.c:1380
msgid "the commit is authored by me now (used with -C/-c/--amend)"
-msgstr "Setze mich als Autor der Version (benutzt mit -C/-c/--amend)"
+msgstr "Setzt Sie als Autor der Version (benutzt mit -C/-c/--amend)"
#: builtin/commit.c:1381 builtin/log.c:1073 builtin/revert.c:109
msgid "add Signed-off-by:"
@@ -3836,7 +3836,7 @@ msgstr "Konnte Versionsbeschreibung nicht lesen: %s"
#: builtin/commit.c:1534
#, c-format
msgid "Aborting commit; you did not edit the message.\n"
-msgstr "Eintragung abgebrochen; du hast die Beschreibung nicht editiert.\n"
+msgstr "Eintragung abgebrochen; Sie haben die Beschreibung nicht editiert.\n"
#: builtin/commit.c:1539
#, c-format
@@ -3862,8 +3862,8 @@ msgid ""
"not exceeded, and then \"git reset HEAD\" to recover."
msgstr ""
"Das Projektarchiv wurde aktualisiert, aber die \"new_index\"-Datei\n"
-"konnte nicht geschrieben werden. Prüfe, dass deine Festplatte nicht\n"
-"voll und Dein Kontingent nicht aufgebraucht ist und führe\n"
+"konnte nicht geschrieben werden. Prüfen Sie, dass Ihre Festplatte nicht\n"
+"voll und Ihr Kontingent nicht aufgebraucht ist und führen Sie\n"
"anschließend \"git reset HEAD\" zu Wiederherstellung aus."
#: builtin/config.c:7
@@ -4041,7 +4041,7 @@ msgid ""
"However, there were unannotated tags: try --tags."
msgstr ""
"Keine annotierten Markierungen können '%s' beschreiben.\n"
-"Jedoch gab es nicht annotierte Markierungen: versuche --tags."
+"Jedoch gab es nicht annotierte Markierungen: versuchen Sie --tags."
#: builtin/describe.c:357
#, c-format
@@ -4050,7 +4050,7 @@ msgid ""
"Try --always, or create some tags."
msgstr ""
"Keine Markierungen können '%s' beschreiben.\n"
-"Versuche --always oder erstelle einige Markierungen."
+"Versuchen Sie --always oder erstellen Sie einige Markierungen."
#: builtin/describe.c:378
#, c-format
@@ -4354,7 +4354,7 @@ msgid ""
"some local refs could not be updated; try running\n"
" 'git remote prune %s' to remove any old, conflicting branches"
msgstr ""
-"Einige lokale Referenzen konnten nicht aktualisiert werden; versuche\n"
+"Einige lokale Referenzen konnten nicht aktualisiert werden; versuchen Sie\n"
"'git remote prune %s' um jeden älteren, widersprüchlichen Zweig zu löschen."
#: builtin/fetch.c:549
@@ -4412,13 +4412,13 @@ msgid ""
"No remote repository specified. Please, specify either a URL or a\n"
"remote name from which new revisions should be fetched."
msgstr ""
-"Kein externes Projektarchiv angegeben. Bitte gebe entweder eine URL\n"
+"Kein externes Projektarchiv angegeben. Bitte geben Sie entweder eine URL\n"
"oder den Namen des externen Archivs an, von welchem neue\n"
"Versionen angefordert werden sollen."
#: builtin/fetch.c:932
msgid "You need to specify a tag name."
-msgstr "Du musst den Namen der Markierung angeben."
+msgstr "Sie müssen den Namen der Markierung angeben."
#: builtin/fetch.c:984
msgid "fetch --all does not take a repository argument"
@@ -4587,15 +4587,15 @@ msgid ""
"run \"git gc\" manually. See \"git help gc\" for more information.\n"
msgstr ""
"Die Datenbank des Projektarchivs wird für eine optimale Performance\n"
-"komprimiert. Du kannst auch \"git gc\" manuell ausführen.\n"
+"komprimiert. Sie können auch \"git gc\" manuell ausführen.\n"
"Siehe \"git help gc\" für weitere Informationen.\n"
#: builtin/gc.c:249
msgid ""
"There are too many unreachable loose objects; run 'git prune' to remove them."
msgstr ""
-"Es gibt zu viele unerreichbare lose Objekte; führe 'git prune' aus, um diese "
-"zu löschen."
+"Es gibt zu viele unerreichbare lose Objekte; führen Sie 'git prune' aus, um "
+"diese zu löschen."
#: builtin/grep.c:22
msgid "git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]"
@@ -4918,7 +4918,7 @@ msgid ""
"Please consider using 'man.<tool>.cmd' instead."
msgstr ""
"'%s': Pfad für nicht unterstützten Handbuchbetrachter.\n"
-"Du könntest stattdessen 'man.<Werkzeug>.cmd' benutzen."
+"Sie könnten stattdessen 'man.<Werkzeug>.cmd' benutzen."
#: builtin/help.c:229
#, c-format
@@ -4927,7 +4927,7 @@ msgid ""
"Please consider using 'man.<tool>.path' instead."
msgstr ""
"'%s': Kommando für unterstützten Handbuchbetrachter.\n"
-"Du könntest stattdessen 'man.<Werkzeug>.path' benutzen."
+"Sie könnten stattdessen 'man.<Werkzeug>.path' benutzen."
#: builtin/help.c:299
msgid "The most commonly used git commands are:"
@@ -5636,8 +5636,8 @@ msgstr "git cherry [-v] [<Ãœbernahmezweig> [<Arbeitszweig> [<Limit>]]]"
msgid ""
"Could not find a tracked remote branch, please specify <upstream> manually.\n"
msgstr ""
-"Konnte gefolgten, externen Zweig nicht finden, bitte gebe <upstream> manuell "
-"an.\n"
+"Konnte gefolgten, externen Zweig nicht finden, bitte geben Sie <upstream> "
+"manuell an.\n"
#: builtin/log.c:1517 builtin/log.c:1519 builtin/log.c:1531
#, c-format
@@ -5956,7 +5956,7 @@ msgstr "konnte nicht von '%s' lesen"
#, c-format
msgid "Not committing merge; use 'git commit' to complete the merge.\n"
msgstr ""
-"Zusammenführung wurde nicht eingetragen; benutze 'git commit' um die "
+"Zusammenführung wurde nicht eingetragen; benutzen Sie 'git commit' um die "
"Zusammenführung abzuschließen.\n"
#: builtin/merge.c:788
@@ -5967,7 +5967,7 @@ msgid ""
"Lines starting with '#' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"Bitte gebe eine Versionsbeschreibung ein um zu erklären, warum diese "
+"Bitte geben Sie eine Versionsbeschreibung ein um zu erklären, warum diese "
"Zusammenführung erforderlich ist,\n"
"insbesondere wenn es einen aktualisierten, externen Zweig mit einem Thema-"
"Zweig zusammenführt.\n"
@@ -5988,8 +5988,8 @@ msgstr "Wunderbar.\n"
#, c-format
msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
msgstr ""
-"Automatische Zusammenführung fehlgeschlagen; behebe die Konflikte und trage "
-"dann das Ergebnis ein.\n"
+"Automatische Zusammenführung fehlgeschlagen; beheben Sie die Konflikte und tragen "
+"Sie dann das Ergebnis ein.\n"
#: builtin/merge.c:905
#, c-format
@@ -5998,7 +5998,7 @@ msgstr "'%s' ist keine Version"
#: builtin/merge.c:946
msgid "No current branch."
-msgstr "Du befindest dich auf keinem Zweig."
+msgstr "Sie befinden sich auf keinem Zweig."
#: builtin/merge.c:948
msgid "No remote for the current branch."
@@ -6029,34 +6029,34 @@ msgid ""
"You have not concluded your merge (MERGE_HEAD exists).\n"
"Please, commit your changes before you can merge."
msgstr ""
-"Du hast deine Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert).\n"
-"Bitte trage deine Änderungen ein, bevor du zusammenführen kannst."
+"Sie haben Ihre Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert).\n"
+"Bitte tragen Sie Ihre Änderungen ein, bevor Sie zusammenführen können."
#: builtin/merge.c:1129 git-pull.sh:34
msgid "You have not concluded your merge (MERGE_HEAD exists)."
msgstr ""
-"Du hast deine Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert)."
+"Sie haben Ihre Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert)."
#: builtin/merge.c:1133
msgid ""
"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
"Please, commit your changes before you can merge."
msgstr ""
-"Du hast \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert).\n"
-"Bitte trage deine Änderungen ein, bevor du zusammenführen kannst."
+"Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert).\n"
+"Bitte tragen Sie Ihre Änderungen ein, bevor Sie zusammenführen können."
#: builtin/merge.c:1136
msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
msgstr ""
-"Du hast \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert)."
+"Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert)."
#: builtin/merge.c:1145
msgid "You cannot combine --squash with --no-ff."
-msgstr "Du kannst --squash nicht mit --no-ff kombinieren."
+msgstr "Sie können --squash nicht mit --no-ff kombinieren."
#: builtin/merge.c:1150
msgid "You cannot combine --no-ff with --ff-only."
-msgstr "Du kannst --no-ff nicht mit --ff--only kombinieren."
+msgstr "Sie können --no-ff nicht mit --ff--only kombinieren."
#: builtin/merge.c:1157
msgid "No commit specified and merge.defaultToUpstream not set."
@@ -6116,7 +6116,7 @@ msgstr "Zusammenführung mit Strategie %s fehlgeschlagen.\n"
#: builtin/merge.c:1491
#, c-format
msgid "Using the %s to prepare resolving by hand.\n"
-msgstr "Benutze \"%s\" um die Auflösung per Hand vorzubereiten.\n"
+msgstr "Benutzen Sie \"%s\" um die Auflösung per Hand vorzubereiten.\n"
#: builtin/merge.c:1503
#, c-format
@@ -6461,7 +6461,7 @@ msgstr "konnte Datei '%s' nicht erstellen"
#: builtin/notes.c:192
msgid "Please supply the note contents using either -m or -F option"
-msgstr "Bitte liefere den Notiz-Inhalt unter Verwendung der Option -m oder -F."
+msgstr "Bitte liefern Sie den Notiz-Inhalt unter Verwendung der Option -m oder -F."
#: builtin/notes.c:213 builtin/notes.c:976
#, c-format
@@ -6575,7 +6575,7 @@ msgid ""
"existing notes"
msgstr ""
"Konnte Notizen nicht hinzufügen. Existierende Notizen für Objekt %s "
-"gefunden. Verwende '-f' um die existierenden Notizen zu überschreiben."
+"gefunden. Verwenden Sie '-f' um die existierenden Notizen zu überschreiben."
#: builtin/notes.c:588 builtin/notes.c:665
#, c-format
@@ -6603,7 +6603,7 @@ msgid ""
"existing notes"
msgstr ""
"Kann Notizen nicht kopieren. Existierende Notizen für Objekt %s gefunden. "
-"Verwende '-f' um die existierenden Notizen zu überschreiben."
+"Verwenden Sie '-f' um die existierenden Notizen zu überschreiben."
#: builtin/notes.c:671
#, c-format
@@ -6617,7 +6617,7 @@ msgid ""
"Please use 'git notes add -f -m/-F/-c/-C' instead.\n"
msgstr ""
"Die Optionen -m/-F/-c/-C sind für das Unterkommando 'edit' veraltet.\n"
-"Bitte benutze stattdessen 'git notes add -f -m/-F/-c/-C'.\n"
+"Bitte benutzen Sie stattdessen 'git notes add -f -m/-F/-c/-C'.\n"
#: builtin/notes.c:867
msgid "General options"
@@ -6908,14 +6908,14 @@ msgid ""
" git push %s %s\n"
"%s"
msgstr ""
-"Der Name des externen Ãœbernahmezweiges stimmt nicht mit dem Namen deines\n"
+"Der Name des externen Ãœbernahmezweiges stimmt nicht mit dem Namen Ihres\n"
"aktuellen Zweiges überein. Um auf den Übernahmezweig in dem externen\n"
-"Projektarchiv zu versenden, benutze:\n"
+"Projektarchiv zu versenden, benutzen Sie:\n"
"\n"
" git push %s HEAD:%s\n"
"\n"
"Um auf den Zweig mit dem selben Namen in dem externen Projekarchiv\n"
-"zu versenden, benutze:\n"
+"zu versenden, benutzen Sie:\n"
"\n"
" git push %s %s\n"
"%s"
@@ -6929,9 +6929,9 @@ msgid ""
"\n"
" git push %s HEAD:<name-of-remote-branch>\n"
msgstr ""
-"Du befindest dich sich im Moment auf keinem Zweig.\n"
+"Sie befinden sich im Moment auf keinem Zweig.\n"
"Um die Historie, führend zum aktuellen (freistehende Zweigspitze (HEAD))\n"
-"Status zu versenden, benutze\n"
+"Status zu versenden, benutzen Sie\n"
"\n"
" git push %s HEAD:<Name-des-externen-Zweiges>\n"
@@ -6945,7 +6945,7 @@ msgid ""
msgstr ""
"Der aktuelle Zweig %s hat keinen Zweig im externen Projektarchiv.\n"
"Um den aktuellen Zweig zu versenden und das Fernarchiv als externes\n"
-"Projektarchiv zu verwenden, benutze\n"
+"Projektarchiv zu verwenden, benutzen Sie\n"
"\n"
" git push --set-upstream %s %s\n"
@@ -6961,7 +6961,7 @@ msgid ""
"your current branch '%s', without telling me what to push\n"
"to update which remote branch."
msgstr ""
-"Du versendest nach '%s', welches kein externes Projektarchiv deines\n"
+"Sie versenden nach '%s', welches kein externes Projektarchiv Ihres\n"
"aktuellen Zweiges '%s' ist, ohne mir mitzuteilen, was ich versenden\n"
"soll, um welchen externen Zweig zu aktualisieren."
@@ -6985,26 +6985,25 @@ msgstr ""
"'push.default' ist nicht gesetzt; der implizit gesetzte Wert\n"
"wird in Git 2.0 von 'matching' nach 'simple' geändert. Um diese Meldung zu\n"
"unterdrücken und das aktuelle Verhalten nach Änderung des Standardwertes\n"
-"beizubehalten, benutze:\n"
+"beizubehalten, benutzen Sie:\n"
" git config --global push.default matching\n"
"\n"
"Um diese Meldung zu unterdrücken und das neue Verhalten jetzt zu "
-"übernehmen,\n"
-"benutze:\n"
+"übernehmen, benutzen Sie:\n"
"\n"
" git config --global push.default simple\n"
"\n"
-"Führe 'git help config' aus und suche nach 'push.default' für weitere "
-"Informationen.\n"
+"Führen Sie 'git help config' aus und suchen Sie nach 'push.default' für "
+"weitere Informationen.\n"
"(Der Modus 'simple' wurde in Git 1.7.11 eingeführt. Benutze den ähnlichen "
-"Modus 'current' anstatt 'simple', falls du gelegentlich ältere Versionen von "
-"Git benutzt.)"
+"Modus 'current' anstatt 'simple', falls Sie gelegentlich ältere Versionen von "
+"Git benutzen.)"
#: builtin/push.c:199
msgid ""
"You didn't specify any refspecs to push, and push.default is \"nothing\"."
msgstr ""
-"Du hast keine Referenzspezifikationen zum Versenden angegeben, und push."
+"Sie haben keine Referenzspezifikationen zum Versenden angegeben, und push."
"default ist \"nothing\"."
#: builtin/push.c:206
@@ -7014,9 +7013,10 @@ msgid ""
"before pushing again.\n"
"See the 'Note about fast-forwards' in 'git push --help' for details."
msgstr ""
-"Aktualisierungen wurden zurückgewiesen, weil die Spitze deines aktuellen\n"
-"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Führe die\n"
-"externen Änderungen zusammen (z.B. 'git pull') bevor du erneut versendest.\n"
+"Aktualisierungen wurden zurückgewiesen, weil die Spitze Ihres aktuellen\n"
+"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Führen Sie\n"
+"die externen Änderungen zusammen (z.B. 'git pull') bevor Sie erneut\n"
+"versenden.\n"
"Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
"für weitere Details."
@@ -7028,8 +7028,8 @@ msgid ""
"to 'simple', 'current' or 'upstream' to push only the current branch."
msgstr ""
"Aktualisierungen wurden zurückgewiesen, weil die Spitze eines versendeten\n"
-"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Wenn du nicht\n"
-"beabsichtigt hast, diesen Zweig zu versenden, kannst du auch den zu "
+"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Wenn Sie nicht\n"
+"beabsichtigt haben, diesen Zweig zu versenden, können Sie auch den zu "
"versendenden\n"
"Zweig spezifizieren oder die Konfigurationsvariable 'push.default' zu "
"'simple', 'current'\n"
@@ -7043,9 +7043,9 @@ msgid ""
"See the 'Note about fast-forwards' in 'git push --help' for details."
msgstr ""
"Aktualisierungen wurden zurückgewiesen, weil die Spitze eines versendeten\n"
-"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Checke diesen\n"
-"Zweig aus und führe die externen Änderungen zusammen (z.B. 'git pull')\n"
-"bevor du erneut versendest.\n"
+"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Checken Sie\n"
+"diesen Zweig aus und führen Sie die externen Änderungen zusammen\n"
+"(z.B. 'git pull') bevor Sie erneut versenden.\n"
"Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
"für weitere Details."
@@ -7077,12 +7077,12 @@ msgid ""
" git push <name>\n"
msgstr ""
"Kein Ziel zum Versenden konfiguriert.\n"
-"Entweder spezifizierst du die URL von der Kommandozeile oder konfigurierst "
+"Entweder spezifizieren Sie die URL von der Kommandozeile oder konfigurieren "
"ein externes Projektarchiv unter Benutzung von\n"
"\n"
" git remote add <Name> <URL>\n"
"\n"
-"und versendest dann unter Benutzung dieses Namens\n"
+"und versenden dann unter Benutzung dieses Namens\n"
"\n"
" git push <Name>\n"
@@ -7331,7 +7331,7 @@ msgid ""
"\t use --mirror=fetch or --mirror=push instead"
msgstr ""
"--mirror ist gefährlich und veraltet; bitte\n"
-"\t benutze stattdessen --mirror=fetch oder --mirror=push"
+"\t benutzen Sie stattdessen --mirror=fetch oder --mirror=push"
#: builtin/remote.c:147
#, c-format
@@ -7440,7 +7440,7 @@ msgstr ""
"Keine Aktualisierung der nicht standardmäßigen Referenzspezifikation zum "
"Abholen\n"
"\t%s\n"
-"\tBitte aktualisiere, falls notwendig, die Konfiguration manuell."
+"\tBitte aktualisieren Sie, falls notwendig, die Konfiguration manuell."
#: builtin/remote.c:683
#, c-format
@@ -7477,11 +7477,11 @@ msgid_plural ""
msgstr[0] ""
"Hinweis: Ein Zweig außerhalb der /refs/remotes/ Hierachie wurde nicht "
"gelöscht;\n"
-"um diesen zu löschen, benutze:"
+"um diesen zu löschen, benutzen Sie:"
msgstr[1] ""
"Hinweis: Einige Zweige außer der /refs/remotes/ Hierarchie wurden nicht "
"entfernt;\n"
-"um diese zu entfernen, benutze:"
+"um diese zu entfernen, benutzen Sie:"
#: builtin/remote.c:943
#, c-format
@@ -7494,7 +7494,7 @@ msgstr " gefolgt"
#: builtin/remote.c:948
msgid " stale (use 'git remote prune' to remove)"
-msgstr " veraltet (benutze 'git remote prune' zum Löschen)"
+msgstr " veraltet (benutzen Sie 'git remote prune' zum Löschen)"
#: builtin/remote.c:950
msgid " ???"
@@ -7647,8 +7647,8 @@ msgstr "Kann Hauptzweig des externen Projektarchivs nicht bestimmen"
#: builtin/remote.c:1218
msgid "Multiple remote HEAD branches. Please choose one explicitly with:"
msgstr ""
-"Mehrere Hauptzweige im externen Projektarchiv. Bitte wähle explizit einen "
-"aus mit:"
+"Mehrere Hauptzweige im externen Projektarchiv. Bitte wählen Sie explizit "
+"einen aus mit:"
#: builtin/remote.c:1228
#, c-format
@@ -7814,7 +7814,7 @@ msgstr "keep"
#: builtin/reset.c:77
msgid "You do not have a valid HEAD."
-msgstr "Du hast keine gültige Zweigspitze (HEAD)."
+msgstr "Sie haben keine gültige Zweigspitze (HEAD)."
#: builtin/reset.c:79
msgid "Failed to find tree of HEAD."
@@ -7881,7 +7881,8 @@ msgstr "--patch ist inkompatibel mit --{hard,mixed,soft}"
#: builtin/reset.c:317
msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
msgstr ""
-"--mixed mit Pfaden ist veraltet; benutze stattdessen 'git reset -- <Pfade>'."
+"--mixed mit Pfaden ist veraltet; benutzen Sie stattdessen "
+"'git reset -- <Pfade>'."
#: builtin/reset.c:319
#, c-format
@@ -7922,7 +7923,7 @@ msgstr ""
" oder: git rev-parse --sq-quote [<Argumente>...]\n"
" oder: git rev-parse [Optionen] [<Argumente>...]\n"
"\n"
-"Führe \"git rev-parse --parseopt -h\" für weitere Informationen bei erster "
+"Führen Sie \"git rev-parse --parseopt -h\" für weitere Informationen bei erster "
"Verwendung aus."
#: builtin/revert.c:22
@@ -8025,8 +8026,8 @@ msgid ""
"(use 'rm -rf' if you really want to remove it including all of its history)"
msgstr ""
"Unterprojekt '%s' (oder ein geschachteltes Unterprojekt hiervon) verwendet\n"
-"ein .git-Verzeichnis (benutze 'rm -rf' wenn du dieses wirklich mitsamt\n"
-"seiner Historie löschen möchtest)"
+"ein .git-Verzeichnis (benutzen Sie 'rm -rf' wenn Sie dieses wirklich mitsamt\n"
+"seiner Historie löschen möchten)"
#: builtin/rm.c:174
#, c-format
@@ -8035,7 +8036,7 @@ msgid ""
"(use -f to force removal)"
msgstr ""
"'%s' hat bereitgestellten Inhalt unterschiedlich zu der Datei und der\n"
-"Zweigspitze (HEAD) (benutze -f um die Entfernung zu erzwingen)"
+"Zweigspitze (HEAD) (benutzen Sie -f um die Entfernung zu erzwingen)"
#: builtin/rm.c:180
#, c-format
@@ -8044,7 +8045,7 @@ msgid ""
"(use --cached to keep the file, or -f to force removal)"
msgstr ""
"'%s' hat Änderungen in der Bereitstellung\n"
-"(benutze --cached um die Datei zu behalten, oder -f um die Entfernung zu "
+"(benutzen Sie --cached um die Datei zu behalten, oder -f um die Entfernung zu "
"erzwingen)"
#: builtin/rm.c:191
@@ -8054,7 +8055,7 @@ msgid ""
"(use --cached to keep the file, or -f to force removal)"
msgstr ""
"'%s' hat lokale Modifikationen\n"
-"(benutze --cached um die Datei zu behalten, oder -f um die Entfernung zu "
+"(benutzen Sie --cached um die Datei zu behalten, oder -f um die Entfernung zu "
"erzwingen)"
#: builtin/rm.c:207
@@ -8334,7 +8335,7 @@ msgid ""
msgstr ""
"\n"
"#\n"
-"# Gebe eine Markierungsbeschreibung ein\n"
+"# Geben Sie eine Markierungsbeschreibung ein.\n"
"# Zeilen, die mit '#' beginnen, werden ignoriert.\n"
"#\n"
@@ -8349,9 +8350,9 @@ msgid ""
msgstr ""
"\n"
"#\n"
-"# Gebe eine Markierungsbeschreibung ein\n"
-"# Zeilen, die mit '#' beginnen, werden behalten; du darfst diese\n"
-"# selbst entfernen wenn du möchtest.\n"
+"# Geben Sie eine Markierungsbeschreibung ein.\n"
+"# Zeilen, die mit '#' beginnen, werden behalten; Sie dürfen diese\n"
+"# selbst entfernen wenn Sie möchten.\n"
"#\n"
#: builtin/tag.c:298
@@ -8790,14 +8791,14 @@ msgstr ""
#: git-am.sh:50
msgid "You need to set your committer info first"
-msgstr "Du musst zuerst die Informationen des Eintragenden setzen."
+msgstr "Sie müssen zuerst die Informationen des Eintragenden setzen."
#: git-am.sh:95
msgid ""
"You seem to have moved HEAD since the last 'am' failure.\n"
"Not rewinding to ORIG_HEAD"
msgstr ""
-"Du scheinst seit dem letzten gescheiterten 'am' die Zweigspitze (HEAD)\n"
+"Sie scheinen seit dem letzten gescheiterten 'am' die Zweigspitze (HEAD)\n"
"geändert zu haben.\n"
"Keine Zurücksetzung zu ORIG_HEAD."
@@ -8808,12 +8809,11 @@ msgid ""
"If you prefer to skip this patch, run \"$cmdline --skip\" instead.\n"
"To restore the original branch and stop patching, run \"$cmdline --abort\"."
msgstr ""
-"Wenn du das Problem gelöst hast, führe \"$cmdline --resolved\" aus.\n"
-"Falls du diesen Patch auslassen möchtest, führe stattdessen \"$cmdline --skip"
-"\" aus.\n"
-"Um den ursprünglichen Zweig wiederherzustellen und die Anwendung der "
-"Patches\n"
-"abzubrechen, führe \"$cmdline --abort\" aus."
+"Wenn Sie das Problem gelöst haben, führen Sie \"$cmdline --resolved\" aus.\n"
+"Falls Sie diesen Patch auslassen möchten, führen Sie stattdessen\n"
+"\"$cmdline --skip\" aus.\n"
+"Um den ursprünglichen Zweig wiederherzustellen und die Anwendung der\n"
+"Patches abzubrechen, führen Sie \"$cmdline --abort\" aus."
#: git-am.sh:121
msgid "Cannot fall back to three-way merge."
@@ -8836,7 +8836,7 @@ msgid ""
"Did you hand edit your patch?\n"
"It does not apply to blobs recorded in its index."
msgstr ""
-"Hast du den Patch per Hand editiert?\n"
+"Haben Sie den Patch per Hand editiert?\n"
"Er kann nicht auf die Blobs in seiner 'index' Zeile angewendet werden."
#: git-am.sh:163
@@ -8877,7 +8877,7 @@ msgstr ""
#: git-am.sh:482
msgid "Please make up your mind. --skip or --abort?"
-msgstr "Bitte werde dir klar. --skip oder --abort?"
+msgstr "Bitte werden Sie sich klar. --skip oder --abort?"
#: git-am.sh:509
msgid "Resolve operation not in progress, we are not resuming."
@@ -8897,11 +8897,11 @@ msgid ""
"To restore the original branch and stop patching run \"$cmdline --abort\"."
msgstr ""
"Patch ist leer. Wurde er falsch aufgeteilt?\n"
-"Wenn du diesen Patch auslassen möchtest, führe stattdessen \"$cmdline --skip"
-"\" aus.\n"
+"Wenn Sie diesen Patch auslassen möchten, führen Sie stattdessen\n"
+"\"$cmdline --skip\" aus.\n"
"Um den ursprünglichen Zweig wiederherzustellen und die Anwendung der "
"Patches\n"
-"abzubrechen, führe \"$cmdline --abort\" aus."
+"abzubrechen, führen Sie \"$cmdline --abort\" aus."
#: git-am.sh:706
msgid "Patch does not have a valid e-mail address."
@@ -8935,9 +8935,9 @@ msgid ""
"If there is nothing left to stage, chances are that something else\n"
"already introduced the same changes; you might want to skip this patch."
msgstr ""
-"Keine Änderungen - hast du vergessen 'git add' zu benutzen?\n"
+"Keine Änderungen - haben Sie vergessen 'git add' zu benutzen?\n"
"Wenn keine Änderungen mehr zum Bereitstellen vorhanden sind, könnten\n"
-"diese bereits anderweitig eingefügt worden sein; du könntest diesen Patch\n"
+"diese bereits anderweitig eingefügt worden sein; Sie könnten diesen Patch\n"
"auslassen."
#: git-am.sh:829
@@ -8945,8 +8945,8 @@ msgid ""
"You still have unmerged paths in your index\n"
"did you forget to use 'git add'?"
msgstr ""
-"Du hast immer noch nicht zusammengeführte Pfade in der Bereitstellung.\n"
-"Hast du vergessen 'git add' zu benutzen?"
+"Sie haben immer noch nicht zusammengeführte Pfade in der Bereitstellung.\n"
+"Haben Sie vergessen 'git add' zu benutzen?"
#: git-am.sh:845
msgid "No changes -- Patch already applied."
@@ -8972,14 +8972,14 @@ msgstr "wende zu leerer Historie an"
#: git-bisect.sh:48
msgid "You need to start by \"git bisect start\""
-msgstr "Du musst mit \"git bisect start\" beginnen."
+msgstr "Sie müssen mit \"git bisect start\" beginnen."
#. TRANSLATORS: Make sure to include [Y] and [n] in your
#. translation. The program will only accept English input
#. at this point.
#: git-bisect.sh:54
msgid "Do you want me to do it for you [Y/n]? "
-msgstr "Willst du, dass ich es für dich mache [Y/n]? "
+msgstr "Wollen Sie, dass ich es für Sie mache [Y/n]? "
#: git-bisect.sh:95
#, sh-format
@@ -9000,7 +9000,7 @@ msgstr "Ungültige Zweigspitze (HEAD) - Zweigspitze (HEAD) wird benötigt"
msgid ""
"Checking out '$start_head' failed. Try 'git bisect reset <validbranch>'."
msgstr ""
-"Auschecken von '$start_head' fehlgeschlagen. Versuche 'git bisect reset "
+"Auschecken von '$start_head' fehlgeschlagen. Versuchen Sie 'git bisect reset "
"<gueltigerzweig>'."
#: git-bisect.sh:140
@@ -9023,7 +9023,7 @@ msgstr "Ungültige Referenz-Eingabe: $arg"
#: git-bisect.sh:232
msgid "Please call 'bisect_state' with at least one argument."
-msgstr "Bitte rufe 'bisect_state' mit mindestens einem Argument auf."
+msgstr "Bitte rufen Sie 'bisect_state' mit mindestens einem Argument auf."
#: git-bisect.sh:244
#, sh-format
@@ -9045,15 +9045,15 @@ msgstr "Warnung: halbiere nur mit einer fehlerhaften Version"
#. at this point.
#: git-bisect.sh:279
msgid "Are you sure [Y/n]? "
-msgstr "Bist du sicher [Y/n]? "
+msgstr "Sind Sie sicher [Y/n]? "
#: git-bisect.sh:289
msgid ""
"You need to give me at least one good and one bad revisions.\n"
"(You can use \"git bisect bad\" and \"git bisect good\" for that.)"
msgstr ""
-"Du musst mindestens eine korrekte und eine fehlerhafte Version angeben.\n"
-"(Du kannst dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
+"Sie müssen mindestens eine korrekte und eine fehlerhafte Version angeben.\n"
+"(Sie können dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
#: git-bisect.sh:292
msgid ""
@@ -9061,10 +9061,10 @@ msgid ""
"You then need to give me at least one good and one bad revisions.\n"
"(You can use \"git bisect bad\" and \"git bisect good\" for that.)"
msgstr ""
-"Du musst mit \"git bisect start\" beginnen.\n"
-"Danach musst du mindestens eine korrekte und eine fehlerhafte Version "
+"Sie müssen mit \"git bisect start\" beginnen.\n"
+"Danach müssen Sie mindestens eine korrekte und eine fehlerhafte Version "
"angeben.\n"
-"(Du kannst dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
+"(Sie können dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
#: git-bisect.sh:347 git-bisect.sh:474
msgid "We are not bisecting."
@@ -9082,7 +9082,7 @@ msgid ""
"Try 'git bisect reset <commit>'."
msgstr ""
"Konnte die ursprüngliche Zweigspitze (HEAD) '$branch' nicht auschecken.\n"
-"Versuche 'git bisect reset <Version>'."
+"Versuchen Sie 'git bisect reset <Version>'."
#: git-bisect.sh:390
msgid "No logfile given"
@@ -9095,7 +9095,7 @@ msgstr "kann $file nicht für das Abspielen lesen"
#: git-bisect.sh:408
msgid "?? what are you talking about?"
-msgstr "?? Was redest du da?"
+msgstr "?? Was reden Sie da?"
#: git-bisect.sh:420
#, sh-format
@@ -9134,14 +9134,14 @@ msgid ""
"Please, fix them up in the work tree, and then use 'git add/rm <file>'\n"
"as appropriate to mark resolution, or use 'git commit -a'."
msgstr ""
-"\"pull\" ist nicht möglich, weil du nicht zusammengeführte Dateien hast.\n"
-"Bitte korrigiere dies im Arbeitsbaum und benutze dann 'git add/rm <Datei>'\n"
-"um die Auflösung entsprechend zu markieren, oder benutze 'git commit -a'."
+"\"pull\" ist nicht möglich, weil Sie nicht zusammengeführte Dateien haben.\n"
+"Bitte korrigieren Sie dies im Arbeitsbaum und benutzen Sie dann 'git add/rm <Datei>'\n"
+"um die Auflösung entsprechend zu markieren, oder benutzen Sie 'git commit -a'."
#: git-pull.sh:25
msgid "Pull is not possible because you have unmerged files."
msgstr ""
-"\"pull\" ist nicht möglich, weil du nicht zusammengeführte Dateien hast."
+"\"pull\" ist nicht möglich, weil Sie nicht zusammengeführte Dateien haben."
#: git-pull.sh:197
msgid "updating an unborn branch with changes added to the index"
@@ -9161,7 +9161,7 @@ msgid ""
"Warning: commit $orig_head."
msgstr ""
"Warnung: Die Anforderung aktualisierte die Spitze des aktuellen Zweiges.\n"
-"Warnung: Spule deinen Arbeitszweig von Version $orig_head vor."
+"Warnung: Spule Ihren Arbeitszweig von Version $orig_head vor."
#: git-pull.sh:254
msgid "Cannot merge multiple branches into empty head"
@@ -9178,12 +9178,12 @@ msgid ""
"To check out the original branch and stop rebasing, run \"git rebase --abort"
"\"."
msgstr ""
-"Wenn du das Problem aufgelöst hast, führe \"git rebase --continue\" aus.\n"
-"Falls du diesen Patch auslassen möchtest, führe stattdessen \"git rebase --"
+"Wenn Sie das Problem aufgelöst haben, führen Sie \"git rebase --continue\" aus.\n"
+"Falls Sie diesen Patch auslassen möchten, führen Sie stattdessen \"git rebase --"
"skip\" aus.\n"
"Um den ursprünglichen Zweig wiederherzustellen und den Neuaufbau "
"abzubrechen,\n"
-"führe \"git rebase --abort\" aus."
+"führen Sie \"git rebase --abort\" aus."
#: git-rebase.sh:160
msgid "The pre-rebase hook refused to rebase."
@@ -9215,7 +9215,7 @@ msgid ""
"You must edit all merge conflicts and then\n"
"mark them as resolved using git add"
msgstr ""
-"Du musst alle Zusammenführungskonflikte editieren und diese dann\n"
+"Sie müssen alle Zusammenführungskonflikte editieren und diese dann\n"
"mittels \"git add\" als aufgelöst markieren"
#: git-rebase.sh:340
@@ -9237,11 +9237,11 @@ msgid ""
msgstr ""
"Es sieht so aus, als ob es das Verzeichnis $state_dir_base bereits gibt\n"
"und es könnte ein anderer Neuaufbau im Gange sein. Wenn das der Fall ist,\n"
-"probiere bitte\n"
+"probieren Sie bitte\n"
"\t$cmd_live_rebase\n"
-"Wenn das nicht der Fall ist, probiere bitte\n"
+"Wenn das nicht der Fall ist, probieren Sie bitte\n"
"\t$cmd_clear_stale_rebase\n"
-"und führe dieses Kommando nochmal aus. Es wird angehalten, falls noch\n"
+"und führen Sie dieses Kommando nochmal aus. Es wird angehalten, falls noch\n"
"etwas Schützenswertes vorhanden ist."
#: git-rebase.sh:404
@@ -9271,7 +9271,7 @@ msgstr "fatal: Zweig $branch_name nicht gefunden"
#: git-rebase.sh:483
msgid "Please commit or stash them."
-msgstr "Bitte trage die Änderungen ein oder benutze \"stash\"."
+msgstr "Bitte tragen Sie die Änderungen ein oder benutzen Sie \"stash\"."
#: git-rebase.sh:501
#, sh-format
@@ -9293,7 +9293,7 @@ msgstr "Änderungen von $mb zu $onto:"
#: git-rebase.sh:524
msgid "First, rewinding head to replay your work on top of it..."
msgstr ""
-"Zunächst wird die Zweigspitze zurückgespult, um deine Änderungen\n"
+"Zunächst wird die Zweigspitze zurückgespult, um Ihre Änderungen\n"
"darauf neu anzuwenden..."
#: git-rebase.sh:532
@@ -9307,7 +9307,7 @@ msgstr "git stash clear mit Parametern ist nicht implementiert"
#: git-stash.sh:74
msgid "You do not have the initial commit yet"
-msgstr "Du hast bisher noch keine initiale Version"
+msgstr "Sie haben bisher noch keine initiale Version"
#: git-stash.sh:89
msgid "Cannot save the current index state"
@@ -9346,7 +9346,7 @@ msgid ""
" To provide a message, use git stash save -- '$option'"
msgstr ""
"Fehler: unbekannte Option für 'stash save': $option\n"
-" Um eine Beschreibung anzugeben, benutze \"git stash save -- "
+" Um eine Beschreibung anzugeben, benutzen Sie \"git stash save -- "
"'$option'\""
#: git-stash.sh:223
@@ -9400,7 +9400,7 @@ msgstr ""
#: git-stash.sh:424
msgid "Conflicts in index. Try without --index."
-msgstr "Konflikte in der Bereitstellung. Versuche es ohne --index."
+msgstr "Konflikte in der Bereitstellung. Versuchen Sie es ohne --index."
#: git-stash.sh:426
msgid "Could not save index tree"
@@ -9430,7 +9430,7 @@ msgstr "Kein Zweigname spezifiziert"
#: git-stash.sh:571
msgid "(To restore them type \"git stash apply\")"
-msgstr "(Zur Wiederherstellung gebe \"git stash apply\" ein)"
+msgstr "(Zur Wiederherstellung geben Sie \"git stash apply\" ein)"
#: git-submodule.sh:89
#, sh-format
@@ -9471,9 +9471,9 @@ msgid ""
"$sm_path\n"
"Use -f if you really want to add it."
msgstr ""
-"Der folgende Pfad wird durch eine deiner \".gitignore\" Dateien ignoriert:\n"
+"Der folgende Pfad wird durch eine Ihrer \".gitignore\" Dateien ignoriert:\n"
"$sm_path\n"
-"Benutze -f wenn du diesen wirklich hinzufügen möchtest."
+"Benutzen Sie -f wenn Sie diesen wirklich hinzufügen möchten."
#: git-submodule.sh:355
#, sh-format
@@ -9497,7 +9497,7 @@ msgstr "Ein Git-Verzeichnis für '$sm_name' wurde lokal gefunden mit den "
msgid ""
"If you want to reuse this local git directory instead of cloning again from"
msgstr ""
-"Wenn du dieses lokale Git-Verzeichnis wiederverwenden möchtest, anstatt "
+"Wenn Sie dieses lokale Git-Verzeichnis wiederverwenden möchtest, anstatt "
"erneut zu klonen"
#: git-submodule.sh:369
@@ -9505,7 +9505,7 @@ msgstr ""
msgid ""
"use the '--force' option. If the local git directory is not the correct repo"
msgstr ""
-"benutze die Option '--force'. Wenn das lokale Git-Verzeichnis nicht das "
+"benutzen Sie die Option '--force'. Wenn das lokale Git-Verzeichnis nicht das "
"korrekte Projektarchiv ist"
#: git-submodule.sh:370
@@ -9514,8 +9514,8 @@ msgid ""
"or you are unsure what this means choose another name with the '--name' "
"option."
msgstr ""
-"oder du dir unsicher bist, was das bedeutet, wähle einen anderen Namen mit "
-"der Option '--name'."
+"oder Sie sich unsicher sind, was das bedeutet, wählen Sie einen anderen Namen"
+"mit der Option '--name'."
#: git-submodule.sh:372
#, sh-format
@@ -9576,7 +9576,7 @@ msgid ""
"Maybe you want to use 'update --init'?"
msgstr ""
"Unterprojekt-Pfad '$sm_path' ist nicht initialisiert\n"
-"Vielleicht möchtest du 'update --init' benutzen?"
+"Vielleicht möchten Sie 'update --init' benutzen?"
#: git-submodule.sh:627
#, sh-format
diff --git a/pretty.c b/pretty.c
index 91bb2d3ef6..92c839fe64 100644
--- a/pretty.c
+++ b/pretty.c
@@ -960,12 +960,19 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
switch (placeholder[0]) {
case 'C':
if (placeholder[1] == '(') {
- const char *end = strchr(placeholder + 2, ')');
+ const char *begin = placeholder + 2;
+ const char *end = strchr(begin, ')');
char color[COLOR_MAXLEN];
+
if (!end)
return 0;
- color_parse_mem(placeholder + 2,
- end - (placeholder + 2),
+ if (!memcmp(begin, "auto,", 5)) {
+ if (!want_color(c->pretty_ctx->color))
+ return end - placeholder + 1;
+ begin += 5;
+ }
+ color_parse_mem(begin,
+ end - begin,
"--pretty format", color);
strbuf_addstr(sb, color);
return end - placeholder + 1;
diff --git a/remote.c b/remote.c
index 6aa49c03df..4b1153f02c 100644
--- a/remote.c
+++ b/remote.c
@@ -1279,12 +1279,34 @@ int match_push_refs(struct ref *src, struct ref **dst,
return 0;
}
+static inline int is_forwardable(struct ref* ref)
+{
+ struct object *o;
+
+ if (!prefixcmp(ref->name, "refs/tags/"))
+ return 0;
+
+ /* old object must be a commit */
+ o = parse_object(ref->old_sha1);
+ if (!o || o->type != OBJ_COMMIT)
+ return 0;
+
+ /* new object must be commit-ish */
+ o = deref_tag(parse_object(ref->new_sha1), NULL, 0);
+ if (!o || o->type != OBJ_COMMIT)
+ return 0;
+
+ return 1;
+}
+
void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
int force_update)
{
struct ref *ref;
for (ref = remote_refs; ref; ref = ref->next) {
+ int force_ref_update = ref->force || force_update;
+
if (ref->peer_ref)
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
else if (!send_mirror)
@@ -1297,34 +1319,55 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
continue;
}
- /* This part determines what can overwrite what.
- * The rules are:
+ /*
+ * The below logic determines whether an individual
+ * refspec A:B can be pushed. The push will succeed
+ * if any of the following are true:
*
- * (0) you can always use --force or +A:B notation to
- * selectively force individual ref pairs.
+ * (1) the remote reference B does not exist
*
- * (1) if the old thing does not exist, it is OK.
+ * (2) the remote reference B is being removed (i.e.,
+ * pushing :B where no source is specified)
*
- * (2) if you do not have the old thing, you are not allowed
- * to overwrite it; you would not know what you are losing
- * otherwise.
+ * (3) the update meets all fast-forwarding criteria:
*
- * (3) if both new and old are commit-ish, and new is a
- * descendant of old, it is OK.
+ * (a) the destination is not under refs/tags/
+ * (b) the old is a commit
+ * (c) the new is a descendant of the old
*
- * (4) regardless of all of the above, removing :B is
- * always allowed.
+ * NOTE: We must actually have the old object in
+ * order to overwrite it in the remote reference,
+ * and the new object must be commit-ish. These are
+ * implied by (b) and (c) respectively.
+ *
+ * (4) it is forced using the +A:B notation, or by
+ * passing the --force argument
*/
- ref->nonfastforward =
- !ref->deletion &&
- !is_null_sha1(ref->old_sha1) &&
- (!has_sha1_file(ref->old_sha1)
- || !ref_newer(ref->new_sha1, ref->old_sha1));
+ ref->not_forwardable = !is_forwardable(ref);
- if (ref->nonfastforward && !ref->force && !force_update) {
- ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
- continue;
+ ref->update =
+ !ref->deletion &&
+ !is_null_sha1(ref->old_sha1);
+
+ if (ref->update) {
+ ref->nonfastforward =
+ !has_sha1_file(ref->old_sha1)
+ || !ref_newer(ref->new_sha1, ref->old_sha1);
+
+ if (ref->not_forwardable) {
+ ref->requires_force = 1;
+ if (!force_ref_update) {
+ ref->status = REF_STATUS_REJECT_ALREADY_EXISTS;
+ continue;
+ }
+ } else if (ref->nonfastforward) {
+ ref->requires_force = 1;
+ if (!force_ref_update) {
+ ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
+ continue;
+ }
+ }
}
}
}
@@ -1370,6 +1413,16 @@ int branch_merge_matches(struct branch *branch,
return refname_match(branch->merge[i]->src, refname, ref_fetch_rules);
}
+static int ignore_symref_update(const char *refname)
+{
+ unsigned char sha1[20];
+ int flag;
+
+ if (!resolve_ref_unsafe(refname, sha1, 0, &flag))
+ return 0; /* non-existing refs are OK */
+ return (flag & REF_ISSYMREF);
+}
+
static struct ref *get_expanded_map(const struct ref *remote_refs,
const struct refspec *refspec)
{
@@ -1383,7 +1436,8 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
if (strchr(ref->name, '^'))
continue; /* a dereference item */
if (match_name_with_pattern(refspec->src, ref->name,
- refspec->dst, &expn_name)) {
+ refspec->dst, &expn_name) &&
+ !ignore_symref_update(expn_name)) {
struct ref *cpy = copy_ref(ref);
cpy->peer_ref = alloc_ref(expn_name);
diff --git a/run-command.c b/run-command.c
index 757f263cd6..24eaad5c66 100644
--- a/run-command.c
+++ b/run-command.c
@@ -725,7 +725,7 @@ error:
int finish_async(struct async *async)
{
#ifdef NO_PTHREADS
- return wait_or_whine(async->pid, "child process", 0);
+ return wait_or_whine(async->pid, "child process");
#else
void *ret = (void *)(intptr_t)(-1);
diff --git a/send-pack.c b/send-pack.c
index f50dfd9f48..1c375f0a28 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -229,6 +229,7 @@ int send_pack(struct send_pack_args *args,
/* Check for statuses set by set_ref_status_for_push() */
switch (ref->status) {
case REF_STATUS_REJECT_NONFASTFORWARD:
+ case REF_STATUS_REJECT_ALREADY_EXISTS:
case REF_STATUS_UPTODATE:
continue;
default:
diff --git a/sequencer.c b/sequencer.c
index 22604902aa..aef5e8a017 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -186,14 +186,15 @@ static int error_dirty_index(struct replay_opts *opts)
return -1;
}
-static int fast_forward_to(const unsigned char *to, const unsigned char *from)
+static int fast_forward_to(const unsigned char *to, const unsigned char *from,
+ int unborn)
{
struct ref_lock *ref_lock;
read_cache();
if (checkout_fast_forward(from, to, 1))
exit(1); /* the callee should have complained already */
- ref_lock = lock_any_ref_for_update("HEAD", from, 0);
+ ref_lock = lock_any_ref_for_update("HEAD", unborn ? null_sha1 : from, 0);
return write_ref_sha1(ref_lock, to, "cherry-pick");
}
@@ -390,7 +391,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
char *defmsg = NULL;
struct strbuf msgbuf = STRBUF_INIT;
- int res;
+ int res, unborn = 0;
if (opts->no_commit) {
/*
@@ -402,9 +403,10 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
if (write_cache_as_tree(head, 0, NULL))
die (_("Your index file is unmerged."));
} else {
- if (get_sha1("HEAD", head))
- return error(_("You do not have a valid HEAD"));
- if (index_differs_from("HEAD", 0))
+ unborn = get_sha1("HEAD", head);
+ if (unborn)
+ hashcpy(head, EMPTY_TREE_SHA1_BIN);
+ if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0))
return error_dirty_index(opts);
}
discard_cache();
@@ -435,8 +437,10 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
else
parent = commit->parents->item;
- if (opts->allow_ff && parent && !hashcmp(parent->object.sha1, head))
- return fast_forward_to(commit->object.sha1, head);
+ if (opts->allow_ff &&
+ ((parent && !hashcmp(parent->object.sha1, head)) ||
+ (!parent && unborn)))
+ return fast_forward_to(commit->object.sha1, head, unborn);
if (parent && parse_commit(parent) < 0)
/* TRANSLATORS: The first %s will be "revert" or
diff --git a/strbuf.c b/strbuf.c
index 05d0693eba..9a373bef70 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -425,6 +425,32 @@ void strbuf_add_lines(struct strbuf *out, const char *prefix,
strbuf_complete_line(out);
}
+void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s)
+{
+ while (*s) {
+ size_t len = strcspn(s, "\"<>&");
+ strbuf_add(buf, s, len);
+ s += len;
+ switch (*s) {
+ case '"':
+ strbuf_addstr(buf, "&quot;");
+ break;
+ case '<':
+ strbuf_addstr(buf, "&lt;");
+ break;
+ case '>':
+ strbuf_addstr(buf, "&gt;");
+ break;
+ case '&':
+ strbuf_addstr(buf, "&amp;");
+ break;
+ case 0:
+ return;
+ }
+ s++;
+ }
+}
+
static int is_rfc3986_reserved(char ch)
{
switch (ch) {
diff --git a/strbuf.h b/strbuf.h
index aa386c6074..ecae4e215f 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -136,6 +136,12 @@ extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);
extern void strbuf_add_lines(struct strbuf *sb, const char *prefix, const char *buf, size_t size);
+/*
+ * Append s to sb, with the characters '<', '>', '&' and '"' converted
+ * into XML entities.
+ */
+extern void strbuf_addstr_xml_quoted(struct strbuf *sb, const char *s);
+
static inline void strbuf_complete_line(struct strbuf *sb)
{
if (sb->len && sb->buf[sb->len - 1] != '\n')
diff --git a/t/Makefile b/t/Makefile
index 3025418ff5..1923cc104b 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -13,9 +13,11 @@ TAR ?= $(TAR)
RM ?= rm -f
PROVE ?= prove
DEFAULT_TEST_TARGET ?= test
+TEST_LINT ?= test-lint-duplicates test-lint-executable
# Shell quote;
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
+PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh))
@@ -43,7 +45,7 @@ clean-except-prove-cache:
clean: clean-except-prove-cache
$(RM) .prove
-test-lint: test-lint-duplicates test-lint-executable
+test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax
test-lint-duplicates:
@dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
@@ -55,6 +57,9 @@ test-lint-executable:
test -z "$$bad" || { \
echo >&2 "non-executable tests:" $$bad; exit 1; }
+test-lint-shell-syntax:
+ @'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T)
+
aggregate-results-and-cleanup: $(T)
$(MAKE) aggregate-results
$(MAKE) clean
@@ -87,7 +92,7 @@ test-results:
mkdir -p test-results
test-results/git-smoke.tar.gz: test-results
- $(PERL_PATH) ./harness \
+ '$(PERL_PATH_SQ)' ./harness \
--archive="test-results/git-smoke.tar.gz" \
$(T)
diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl
new file mode 100755
index 0000000000..8b5a71dc05
--- /dev/null
+++ b/t/check-non-portable-shell.pl
@@ -0,0 +1,27 @@
+#!/usr/bin/perl
+
+# Test t0000..t9999.sh for non portable shell scripts
+# This script can be called with one or more filenames as parameters
+
+use strict;
+use warnings;
+
+my $exit_code=0;
+
+sub err {
+ my $msg = shift;
+ print "$ARGV:$.: error: $msg: $_\n";
+ $exit_code = 1;
+}
+
+while (<>) {
+ chomp;
+ /^\s*sed\s+-i/ and err 'sed -i is not portable';
+ /^\s*echo\s+-n/ and err 'echo -n is not portable (please use printf)';
+ /^\s*declare\s+/ and err 'arrays/declare not portable';
+ /^\s*[^#]\s*which\s/ and err 'which is not portable (please use type)';
+ /test\s+[^=]*==/ and err '"test a == b" is not portable (please use =)';
+ # this resets our $. for each file
+ close ARGV if eof;
+}
+exit $exit_code;
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 807b8b88e2..43b25137e9 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -206,6 +206,43 @@ test_expect_success 'patterns starting with exclamation' '
attr_check "!f" foo
'
+test_expect_success '"**" test' '
+ echo "**/f foo=bar" >.gitattributes &&
+ cat <<\EOF >expect &&
+f: foo: bar
+a/f: foo: bar
+a/b/f: foo: bar
+a/b/c/f: foo: bar
+EOF
+ git check-attr foo -- "f" >actual 2>err &&
+ git check-attr foo -- "a/f" >>actual 2>>err &&
+ git check-attr foo -- "a/b/f" >>actual 2>>err &&
+ git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
+ test_cmp expect actual &&
+ test_line_count = 0 err
+'
+
+test_expect_success '"**" with no slashes test' '
+ echo "a**f foo=bar" >.gitattributes &&
+ git check-attr foo -- "f" >actual &&
+ cat <<\EOF >expect &&
+f: foo: unspecified
+af: foo: bar
+axf: foo: bar
+a/f: foo: unspecified
+a/b/f: foo: unspecified
+a/b/c/f: foo: unspecified
+EOF
+ git check-attr foo -- "f" >actual 2>err &&
+ git check-attr foo -- "af" >>actual 2>err &&
+ git check-attr foo -- "axf" >>actual 2>err &&
+ git check-attr foo -- "a/f" >>actual 2>>err &&
+ git check-attr foo -- "a/b/f" >>actual 2>>err &&
+ git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
+ test_cmp expect actual &&
+ test_line_count = 0 err
+'
+
test_expect_success 'setup bare' '
git clone --bare . bare.git &&
cd bare.git
diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh
index e23ac0e69d..1e2945ec7e 100755
--- a/t/t1020-subdirectory.sh
+++ b/t/t1020-subdirectory.sh
@@ -111,19 +111,19 @@ test_expect_success 'read-tree' '
test_expect_success 'alias expansion' '
(
- git config alias.ss status &&
+ git config alias.test-status-alias status &&
cd dir &&
git status &&
- git ss
+ git test-status-alias
)
'
test_expect_success NOT_MINGW '!alias expansion' '
pwd >expect &&
(
- git config alias.test !pwd &&
+ git config alias.test-alias-directory !pwd &&
cd dir &&
- git test >../actual
+ git test-alias-directory >../actual
) &&
test_cmp expect actual
'
@@ -131,9 +131,9 @@ test_expect_success NOT_MINGW '!alias expansion' '
test_expect_success 'GIT_PREFIX for !alias' '
printf "dir/" >expect &&
(
- git config alias.test "!sh -c \"printf \$GIT_PREFIX\"" &&
+ git config alias.test-alias-directory "!sh -c \"printf \$GIT_PREFIX\"" &&
cd dir &&
- git test >../actual
+ git test-alias-directory >../actual
) &&
test_cmp expect actual
'
diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh
index 1ae4d87c92..1a5a5f39fd 100755
--- a/t/t1402-check-ref-format.sh
+++ b/t/t1402-check-ref-format.sh
@@ -11,7 +11,8 @@ valid_ref() {
prereq=$1
shift
esac
- test_expect_success $prereq "ref name '$1' is valid${2:+ with options $2}" "
+ desc="ref name '$1' is valid${2:+ with options $2}"
+ test_expect_success $prereq "$desc" "
git check-ref-format $2 '$1'
"
}
@@ -22,7 +23,8 @@ invalid_ref() {
prereq=$1
shift
esac
- test_expect_success $prereq "ref name '$1' is invalid${2:+ with options $2}" "
+ desc="ref name '$1' is invalid${2:+ with options $2}"
+ test_expect_success $prereq "$desc" "
test_must_fail git check-ref-format $2 '$1'
"
}
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 08aa24ca15..d730734fde 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -237,4 +237,35 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' '
)
'
+test_expect_success 'fsck notices "." and ".." in trees' '
+ (
+ git init dots &&
+ cd dots &&
+ blob=$(echo foo | git hash-object -w --stdin) &&
+ tab=$(printf "\\t") &&
+ git mktree <<-EOF &&
+ 100644 blob $blob$tab.
+ 100644 blob $blob$tab..
+ EOF
+ git fsck 2>out &&
+ cat out &&
+ grep "warning.*\\." out
+ )
+'
+
+test_expect_success 'fsck notices ".git" in trees' '
+ (
+ git init dotgit &&
+ cd dotgit &&
+ blob=$(echo foo | git hash-object -w --stdin) &&
+ tab=$(printf "\\t") &&
+ git mktree <<-EOF &&
+ 100644 blob $blob$tab.git
+ EOF
+ git fsck 2>out &&
+ cat out &&
+ grep "warning.*\\.git" out
+ )
+'
+
test_done
diff --git a/t/t1505-rev-parse-last.sh b/t/t1505-rev-parse-last.sh
index d709ecf8df..4969edb314 100755
--- a/t/t1505-rev-parse-last.sh
+++ b/t/t1505-rev-parse-last.sh
@@ -32,32 +32,24 @@ test_expect_success 'setup' '
#
# and 'side' should be the last branch
-test_rev_equivalent () {
-
- git rev-parse "$1" > expect &&
- git rev-parse "$2" > output &&
- test_cmp expect output
-
-}
-
test_expect_success '@{-1} works' '
- test_rev_equivalent side @{-1}
+ test_cmp_rev side @{-1}
'
test_expect_success '@{-1}~2 works' '
- test_rev_equivalent side~2 @{-1}~2
+ test_cmp_rev side~2 @{-1}~2
'
test_expect_success '@{-1}^2 works' '
- test_rev_equivalent side^2 @{-1}^2
+ test_cmp_rev side^2 @{-1}^2
'
test_expect_success '@{-1}@{1} works' '
- test_rev_equivalent side@{1} @{-1}@{1}
+ test_cmp_rev side@{1} @{-1}@{1}
'
test_expect_success '@{-2} works' '
- test_rev_equivalent master @{-2}
+ test_cmp_rev master @{-2}
'
test_expect_success '@{-3} fails' '
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index dc2f0458fd..efb7ebc91f 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -220,4 +220,22 @@ test_expect_success 'pattern matches prefix completely' '
test_cmp expect actual
'
+test_expect_success 'ls-files with "**" patterns' '
+ cat <<\EOF >expect &&
+a.1
+one/a.1
+one/two/a.1
+three/a.1
+EOF
+ git ls-files -o -i --exclude "**/a.1" >actual
+ test_cmp expect actual
+'
+
+
+test_expect_success 'ls-files with "**" patterns and no slashes' '
+ : >expect &&
+ git ls-files -o -i --exclude "one**a.1" >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
new file mode 100755
index 0000000000..af54c83111
--- /dev/null
+++ b/t/t3070-wildmatch.sh
@@ -0,0 +1,195 @@
+#!/bin/sh
+
+test_description='wildmatch tests'
+
+. ./test-lib.sh
+
+match() {
+ if [ $1 = 1 ]; then
+ test_expect_success "wildmatch: match '$3' '$4'" "
+ test-wildmatch wildmatch '$3' '$4'
+ "
+ else
+ test_expect_success "wildmatch: no match '$3' '$4'" "
+ ! test-wildmatch wildmatch '$3' '$4'
+ "
+ fi
+ if [ $2 = 1 ]; then
+ test_expect_success "fnmatch: match '$3' '$4'" "
+ test-wildmatch fnmatch '$3' '$4'
+ "
+ elif [ $2 = 0 ]; then
+ test_expect_success "fnmatch: no match '$3' '$4'" "
+ ! test-wildmatch fnmatch '$3' '$4'
+ "
+# else
+# test_expect_success BROKEN_FNMATCH "fnmatch: '$3' '$4'" "
+# ! test-wildmatch fnmatch '$3' '$4'
+# "
+ fi
+}
+
+# Basic wildmat features
+match 1 1 foo foo
+match 0 0 foo bar
+match 1 1 '' ""
+match 1 1 foo '???'
+match 0 0 foo '??'
+match 1 1 foo '*'
+match 1 1 foo 'f*'
+match 0 0 foo '*f'
+match 1 1 foo '*foo*'
+match 1 1 foobar '*ob*a*r*'
+match 1 1 aaaaaaabababab '*ab'
+match 1 1 'foo*' 'foo\*'
+match 0 0 foobar 'foo\*bar'
+match 1 1 'f\oo' 'f\\oo'
+match 1 1 ball '*[al]?'
+match 0 0 ten '[ten]'
+match 0 1 ten '**[!te]'
+match 0 0 ten '**[!ten]'
+match 1 1 ten 't[a-g]n'
+match 0 0 ten 't[!a-g]n'
+match 1 1 ton 't[!a-g]n'
+match 1 1 ton 't[^a-g]n'
+match 1 x 'a]b' 'a[]]b'
+match 1 x a-b 'a[]-]b'
+match 1 x 'a]b' 'a[]-]b'
+match 0 x aab 'a[]-]b'
+match 1 x aab 'a[]a-]b'
+match 1 1 ']' ']'
+
+# Extended slash-matching features
+match 0 0 'foo/baz/bar' 'foo*bar'
+match 0 0 'foo/baz/bar' 'foo**bar'
+match 0 1 'foobazbar' 'foo**bar'
+match 1 1 'foo/baz/bar' 'foo/**/bar'
+match 1 0 'foo/baz/bar' 'foo/**/**/bar'
+match 1 0 'foo/b/a/z/bar' 'foo/**/bar'
+match 1 0 'foo/b/a/z/bar' 'foo/**/**/bar'
+match 1 0 'foo/bar' 'foo/**/bar'
+match 1 0 'foo/bar' 'foo/**/**/bar'
+match 0 0 'foo/bar' 'foo?bar'
+match 0 0 'foo/bar' 'foo[/]bar'
+match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 0 'foo' '**/foo'
+match 1 x 'XXX/foo' '**/foo'
+match 1 0 'bar/baz/foo' '**/foo'
+match 0 0 'bar/baz/foo' '*/foo'
+match 0 0 'foo/bar/baz' '**/bar*'
+match 1 0 'deep/foo/bar/baz' '**/bar/*'
+match 0 0 'deep/foo/bar/baz/' '**/bar/*'
+match 1 0 'deep/foo/bar/baz/' '**/bar/**'
+match 0 0 'deep/foo/bar' '**/bar/*'
+match 1 0 'deep/foo/bar/' '**/bar/**'
+match 0 0 'foo/bar/baz' '**/bar**'
+match 1 0 'foo/bar/baz/x' '*/bar/**'
+match 0 0 'deep/foo/bar/baz/x' '*/bar/**'
+match 1 0 'deep/foo/bar/baz/x' '**/bar/*/*'
+
+# Various additional tests
+match 0 0 'acrt' 'a[c-c]st'
+match 1 1 'acrt' 'a[c-c]rt'
+match 0 0 ']' '[!]-]'
+match 1 x 'a' '[!]-]'
+match 0 0 '' '\'
+match 0 x '\' '\'
+match 0 x 'XXX/\' '*/\'
+match 1 x 'XXX/\' '*/\\'
+match 1 1 'foo' 'foo'
+match 1 1 '@foo' '@foo'
+match 0 0 'foo' '@foo'
+match 1 1 '[ab]' '\[ab]'
+match 1 1 '[ab]' '[[]ab]'
+match 1 x '[ab]' '[[:]ab]'
+match 0 x '[ab]' '[[::]ab]'
+match 1 x '[ab]' '[[:digit]ab]'
+match 1 x '[ab]' '[\[:]ab]'
+match 1 1 '?a?b' '\??\?b'
+match 1 1 'abc' '\a\b\c'
+match 0 0 'foo' ''
+match 1 0 'foo/bar/baz/to' '**/t[o]'
+
+# Character class tests
+match 1 x 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+match 0 x 'a' '[[:digit:][:upper:][:space:]]'
+match 1 x 'A' '[[:digit:][:upper:][:space:]]'
+match 1 x '1' '[[:digit:][:upper:][:space:]]'
+match 0 x '1' '[[:digit:][:upper:][:spaci:]]'
+match 1 x ' ' '[[:digit:][:upper:][:space:]]'
+match 0 x '.' '[[:digit:][:upper:][:space:]]'
+match 1 x '.' '[[:digit:][:punct:][:space:]]'
+match 1 x '5' '[[:xdigit:]]'
+match 1 x 'f' '[[:xdigit:]]'
+match 1 x 'D' '[[:xdigit:]]'
+match 1 x '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 x '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 x '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+match 1 x '5' '[a-c[:digit:]x-z]'
+match 1 x 'b' '[a-c[:digit:]x-z]'
+match 1 x 'y' '[a-c[:digit:]x-z]'
+match 0 x 'q' '[a-c[:digit:]x-z]'
+
+# Additional tests, including some malformed wildmats
+match 1 x ']' '[\\-^]'
+match 0 0 '[' '[\\-^]'
+match 1 x '-' '[\-_]'
+match 1 x ']' '[\]]'
+match 0 0 '\]' '[\]]'
+match 0 0 '\' '[\]]'
+match 0 0 'ab' 'a[]b'
+match 0 x 'a[]b' 'a[]b'
+match 0 x 'ab[' 'ab['
+match 0 0 'ab' '[!'
+match 0 0 'ab' '[-'
+match 1 1 '-' '[-]'
+match 0 0 '-' '[a-'
+match 0 0 '-' '[!a-'
+match 1 x '-' '[--A]'
+match 1 x '5' '[--A]'
+match 1 1 ' ' '[ --]'
+match 1 1 '$' '[ --]'
+match 1 1 '-' '[ --]'
+match 0 0 '0' '[ --]'
+match 1 x '-' '[---]'
+match 1 x '-' '[------]'
+match 0 0 'j' '[a-e-n]'
+match 1 x '-' '[a-e-n]'
+match 1 x 'a' '[!------]'
+match 0 0 '[' '[]-a]'
+match 1 x '^' '[]-a]'
+match 0 0 '^' '[!]-a]'
+match 1 x '[' '[!]-a]'
+match 1 1 '^' '[a^bc]'
+match 1 x '-b]' '[a-]b]'
+match 0 0 '\' '[\]'
+match 1 1 '\' '[\\]'
+match 0 0 '\' '[!\\]'
+match 1 1 'G' '[A-\\]'
+match 0 0 'aaabbb' 'b*a'
+match 0 0 'aabcaa' '*ba*'
+match 1 1 ',' '[,]'
+match 1 1 ',' '[\\,]'
+match 1 1 '\' '[\\,]'
+match 1 1 '-' '[,-.]'
+match 0 0 '+' '[,-.]'
+match 0 0 '-.]' '[,-.]'
+match 1 1 '2' '[\1-\3]'
+match 1 1 '3' '[\1-\3]'
+match 0 0 '4' '[\1-\3]'
+match 1 1 '\' '[[-\]]'
+match 1 1 '[' '[[-\]]'
+match 1 1 ']' '[[-\]]'
+match 0 0 '-' '[[-\]]'
+
+# Test recursion and the abort code (use "wildtest -i" to see iteration counts)
+match 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+
+test_done
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 32fdc9938e..8462be1db6 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -29,12 +29,6 @@ Initial setup:
. "$TEST_DIRECTORY"/lib-rebase.sh
-test_cmp_rev () {
- git rev-parse --verify "$1" >expect.rev &&
- git rev-parse --verify "$2" >actual.rev &&
- test_cmp expect.rev actual.rev
-}
-
set_fake_editor
# WARNING: Modifications to the initial repository can change the SHA ID used
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 34c86e5de6..6f489e20ee 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -100,4 +100,13 @@ test_expect_success 'revert forbidden on dirty working tree' '
'
+test_expect_success 'chery-pick on unborn branch' '
+ git checkout --orphan unborn &&
+ git rm --cached -r . &&
+ rm -rf * &&
+ git cherry-pick initial &&
+ git diff --quiet initial &&
+ ! test_cmp_rev initial HEAD
+'
+
test_done
diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh
index 51ca391e47..373aad623c 100755
--- a/t/t3506-cherry-pick-ff.sh
+++ b/t/t3506-cherry-pick-ff.sh
@@ -105,4 +105,12 @@ test_expect_success 'cherry pick a root commit with --ff' '
test "$(git rev-parse --verify HEAD)" = "1df192cd8bc58a2b275d842cede4d221ad9000d1"
'
+test_expect_success 'chery-pick --ff on unborn branch' '
+ git checkout --orphan unborn &&
+ git rm --cached -r . &&
+ rm -rf * &&
+ git cherry-pick --ff first &&
+ test_cmp_rev first HEAD
+'
+
test_done
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index c82f7210c4..223b98433c 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -11,12 +11,6 @@ test_description='test cherry-pick and revert with conflicts
. ./test-lib.sh
-test_cmp_rev () {
- git rev-parse --verify "$1" >expect.rev &&
- git rev-parse --verify "$2" >actual.rev &&
- test_cmp expect.rev actual.rev
-}
-
pristine_detach () {
git checkout -f "$1^0" &&
git read-tree -u --reset HEAD &&
diff --git a/t/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh
index 340afc760d..4e7136b837 100755
--- a/t/t3508-cherry-pick-many-commits.sh
+++ b/t/t3508-cherry-pick-many-commits.sh
@@ -5,15 +5,11 @@ test_description='test cherry-picking many commits'
. ./test-lib.sh
check_head_differs_from() {
- head=$(git rev-parse --verify HEAD) &&
- arg=$(git rev-parse --verify "$1") &&
- test "$head" != "$arg"
+ ! test_cmp_rev HEAD "$1"
}
check_head_equals() {
- head=$(git rev-parse --verify HEAD) &&
- arg=$(git rev-parse --verify "$1") &&
- test "$head" = "$arg"
+ test_cmp_rev HEAD "$1"
}
test_expect_success setup '
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index b5fb527b2e..7b7a89dbd5 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -24,12 +24,6 @@ pristine_detach () {
git clean -d -f -f -q -x
}
-test_cmp_rev () {
- git rev-parse --verify "$1" >expect.rev &&
- git rev-parse --verify "$2" >actual.rev &&
- test_cmp expect.rev actual.rev
-}
-
test_expect_success setup '
git config advice.detachedhead false &&
echo unrelated >unrelated &&
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 90fd598c74..dc0d8ae928 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -963,4 +963,46 @@ test_expect_success 'format patch ignores color.ui' '
test_cmp expect actual
'
+test_expect_success 'cover letter using branch description (1)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter master >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (2)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (3)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (4)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter master.. >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (5)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter -2 HEAD >actual &&
+ grep hello actual >/dev/null
+'
+
+test_expect_success 'cover letter using branch description (6)' '
+ git checkout rebuild-1 &&
+ test_config branch.rebuild-1.description hello &&
+ git format-patch --stdout --cover-letter -2 >actual &&
+ grep hello actual >/dev/null
+'
+
test_done
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
index 1f182f612c..aae30d97b1 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -149,6 +149,104 @@ test_expect_success 'No mailmap files, but configured' '
test_cmp expect actual
'
+test_expect_success 'setup mailmap blob tests' '
+ git checkout -b map &&
+ test_when_finished "git checkout master" &&
+ cat >just-bugs <<-\EOF &&
+ Blob Guy <bugs@company.xx>
+ EOF
+ cat >both <<-\EOF &&
+ Blob Guy <author@example.com>
+ Blob Guy <bugs@company.xx>
+ EOF
+ git add just-bugs both &&
+ git commit -m "my mailmaps" &&
+ echo "Repo Guy <author@example.com>" >.mailmap &&
+ echo "Internal Guy <author@example.com>" >internal.map
+'
+
+test_expect_success 'mailmap.blob set' '
+ cat >expect <<-\EOF &&
+ Blob Guy (1):
+ second
+
+ Repo Guy (1):
+ initial
+
+ EOF
+ git -c mailmap.blob=map:just-bugs shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'mailmap.blob overrides .mailmap' '
+ cat >expect <<-\EOF &&
+ Blob Guy (2):
+ initial
+ second
+
+ EOF
+ git -c mailmap.blob=map:both shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'mailmap.file overrides mailmap.blob' '
+ cat >expect <<-\EOF &&
+ Blob Guy (1):
+ second
+
+ Internal Guy (1):
+ initial
+
+ EOF
+ git \
+ -c mailmap.blob=map:both \
+ -c mailmap.file=internal.map \
+ shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'mailmap.blob can be missing' '
+ cat >expect <<-\EOF &&
+ Repo Guy (1):
+ initial
+
+ nick1 (1):
+ second
+
+ EOF
+ git -c mailmap.blob=map:nonexistent shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'mailmap.blob defaults to off in non-bare repo' '
+ git init non-bare &&
+ (
+ cd non-bare &&
+ test_commit one .mailmap "Fake Name <author@example.com>" &&
+ echo " 1 Fake Name" >expect &&
+ git shortlog -ns HEAD >actual &&
+ test_cmp expect actual &&
+ rm .mailmap &&
+ echo " 1 A U Thor" >expect &&
+ git shortlog -ns HEAD >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'mailmap.blob defaults to HEAD:.mailmap in bare repo' '
+ git clone --bare non-bare bare &&
+ (
+ cd bare &&
+ echo " 1 Fake Name" >expect &&
+ git shortlog -ns HEAD >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'cleanup after mailmap.blob tests' '
+ rm -f .mailmap
+'
+
# Extended mailmap configurations should give us the following output for shortlog
cat >expect <<\EOF
A U Thor <author@example.com> (1):
diff --git a/t/t5002-archive-attr-pattern.sh b/t/t5002-archive-attr-pattern.sh
new file mode 100755
index 0000000000..0c847fb454
--- /dev/null
+++ b/t/t5002-archive-attr-pattern.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+test_description='git archive attribute pattern tests'
+
+. ./test-lib.sh
+
+test_expect_exists() {
+ test_expect_success " $1 exists" "test -e $1"
+}
+
+test_expect_missing() {
+ test_expect_success " $1 does not exist" "test ! -e $1"
+}
+
+test_expect_success 'setup' '
+ echo ignored >ignored &&
+ echo ignored export-ignore >>.git/info/attributes &&
+ git add ignored &&
+
+ mkdir not-ignored-dir &&
+ echo ignored-in-tree >not-ignored-dir/ignored &&
+ echo not-ignored-in-tree >not-ignored-dir/ignored-only-if-dir &&
+ git add not-ignored-dir &&
+
+ mkdir ignored-only-if-dir &&
+ echo ignored by ignored dir >ignored-only-if-dir/ignored-by-ignored-dir &&
+ echo ignored-only-if-dir/ export-ignore >>.git/info/attributes &&
+ git add ignored-only-if-dir &&
+
+
+ mkdir -p one-level-lower/two-levels-lower/ignored-only-if-dir &&
+ echo ignored by ignored dir >one-level-lower/two-levels-lower/ignored-only-if-dir/ignored-by-ignored-dir &&
+ git add one-level-lower &&
+
+ git commit -m. &&
+
+ git clone --bare . bare &&
+ cp .git/info/attributes bare/info/attributes
+'
+
+test_expect_success 'git archive' '
+ git archive HEAD >archive.tar &&
+ (mkdir archive && cd archive && "$TAR" xf -) <archive.tar
+'
+
+test_expect_missing archive/ignored
+test_expect_missing archive/not-ignored-dir/ignored
+test_expect_exists archive/not-ignored-dir/ignored-only-if-dir
+test_expect_exists archive/not-ignored-dir/
+test_expect_missing archive/ignored-only-if-dir/
+test_expect_missing archive/ignored-ony-if-dir/ignored-by-ignored-dir
+test_expect_exists archive/one-level-lower/
+test_expect_missing archive/one-level-lower/two-levels-lower/ignored-only-if-dir/
+test_expect_missing archive/one-level-lower/two-levels-lower/ignored-ony-if-dir/ignored-by-ignored-dir
+
+
+test_done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index b5417cc951..60093728fe 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -368,7 +368,7 @@ test_expect_success 'push with colon-less refspec (2)' '
git branch -D frotz
fi &&
git tag -f frotz &&
- git push testrepo frotz &&
+ git push -f testrepo frotz &&
check_push_result $the_commit tags/frotz &&
check_push_result $the_first_commit heads/frotz
@@ -929,6 +929,48 @@ test_expect_success 'push into aliased refs (inconsistent)' '
)
'
+test_expect_success 'push requires --force to update lightweight tag' '
+ mk_test heads/master &&
+ mk_child child1 &&
+ mk_child child2 &&
+ (
+ cd child1 &&
+ git tag Tag &&
+ git push ../child2 Tag &&
+ git push ../child2 Tag &&
+ >file1 &&
+ git add file1 &&
+ git commit -m "file1" &&
+ git tag -f Tag &&
+ test_must_fail git push ../child2 Tag &&
+ git push --force ../child2 Tag &&
+ git tag -f Tag &&
+ test_must_fail git push ../child2 Tag HEAD~ &&
+ git push --force ../child2 Tag
+ )
+'
+
+test_expect_success 'push requires --force to update annotated tag' '
+ mk_test heads/master &&
+ mk_child child1 &&
+ mk_child child2 &&
+ (
+ cd child1 &&
+ git tag -a -m "message 1" Tag &&
+ git push ../child2 Tag:refs/tmp/Tag &&
+ git push ../child2 Tag:refs/tmp/Tag &&
+ >file1 &&
+ git add file1 &&
+ git commit -m "file1" &&
+ git tag -f -a -m "message 2" Tag &&
+ test_must_fail git push ../child2 Tag:refs/tmp/Tag &&
+ git push --force ../child2 Tag:refs/tmp/Tag &&
+ git tag -f -a -m "message 3" Tag HEAD~ &&
+ test_must_fail git push ../child2 Tag:refs/tmp/Tag &&
+ git push --force ../child2 Tag:refs/tmp/Tag
+ )
+'
+
test_expect_success 'push --porcelain' '
mk_empty &&
echo >.git/foo "To testrepo" &&
diff --git a/t/t5535-fetch-push-symref.sh b/t/t5535-fetch-push-symref.sh
new file mode 100755
index 0000000000..8ed58d27f2
--- /dev/null
+++ b/t/t5535-fetch-push-symref.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+test_description='avoiding conflicting update thru symref aliasing'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit one &&
+ git clone . src &&
+ git clone src dst1 &&
+ git clone src dst2 &&
+ test_commit two &&
+ ( cd src && git pull )
+'
+
+test_expect_success 'push' '
+ (
+ cd src &&
+ git push ../dst1 "refs/remotes/*:refs/remotes/*"
+ ) &&
+ git ls-remote src "refs/remotes/*" >expect &&
+ git ls-remote dst1 "refs/remotes/*" >actual &&
+ test_cmp expect actual &&
+ ( cd src && git symbolic-ref refs/remotes/origin/HEAD ) >expect &&
+ ( cd dst1 && git symbolic-ref refs/remotes/origin/HEAD ) >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'fetch' '
+ (
+ cd dst2 &&
+ git fetch ../src "refs/remotes/*:refs/remotes/*"
+ ) &&
+ git ls-remote src "refs/remotes/*" >expect &&
+ git ls-remote dst2 "refs/remotes/*" >actual &&
+ test_cmp expect actual &&
+ ( cd src && git symbolic-ref refs/remotes/origin/HEAD ) >expect &&
+ ( cd dst2 && git symbolic-ref refs/remotes/origin/HEAD ) >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-testpy.sh
index e7dc668cef..6750961507 100755
--- a/t/t5800-remote-helpers.sh
+++ b/t/t5800-remote-testpy.sh
@@ -3,12 +3,12 @@
# Copyright (c) 2010 Sverre Rabbelier
#
-test_description='Test remote-helper import and export commands'
+test_description='Test python remote-helper framework'
. ./test-lib.sh
if ! test_have_prereq PYTHON ; then
- skip_all='skipping git-remote-hg tests, python not available'
+ skip_all='skipping python remote-helper tests, python not available'
test_done
fi
@@ -17,7 +17,7 @@ import sys
if sys.hexversion < 0x02040000:
sys.exit(1)
' || {
- skip_all='skipping git-remote-hg tests, python version < 2.4'
+ skip_all='skipping python remote-helper tests, python version < 2.4'
test_done
}
@@ -38,12 +38,12 @@ test_expect_success 'setup repository' '
'
test_expect_success 'cloning from local repo' '
- git clone "testgit::${PWD}/server" localclone &&
+ git clone "testpy::${PWD}/server" localclone &&
test_cmp public/file localclone/file
'
test_expect_success 'cloning from remote repo' '
- git clone "testgit::file://${PWD}/server" clone &&
+ git clone "testpy::file://${PWD}/server" clone &&
test_cmp public/file clone/file
'
@@ -73,11 +73,11 @@ test_expect_success 'pushing to local repo' '
'
# Generally, skip this test. It demonstrates a now-fixed race in
-# git-remote-testgit, but is too slow to leave in for general use.
+# git-remote-testpy, but is too slow to leave in for general use.
: test_expect_success 'racily pushing to local repo' '
test_when_finished "rm -rf server2 localclone2" &&
cp -R server server2 &&
- git clone "testgit::${PWD}/server2" localclone2 &&
+ git clone "testpy::${PWD}/server2" localclone2 &&
(cd localclone2 &&
echo content >>file &&
git commit -a -m three &&
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
new file mode 100755
index 0000000000..f387027c05
--- /dev/null
+++ b/t/t5801-remote-helpers.sh
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Sverre Rabbelier
+#
+
+test_description='Test remote-helper import and export commands'
+
+. ./test-lib.sh
+
+if ! type "${BASH-bash}" >/dev/null 2>&1; then
+ skip_all='skipping remote-testgit tests, bash not available'
+ test_done
+fi
+
+compare_refs() {
+ git --git-dir="$1/.git" rev-parse --verify $2 >expect &&
+ git --git-dir="$3/.git" rev-parse --verify $4 >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'setup repository' '
+ git init server &&
+ (cd server &&
+ echo content >file &&
+ git add file &&
+ git commit -m one)
+'
+
+test_expect_success 'cloning from local repo' '
+ git clone "testgit::${PWD}/server" local &&
+ test_cmp server/file local/file
+'
+
+test_expect_success 'create new commit on remote' '
+ (cd server &&
+ echo content >>file &&
+ git commit -a -m two)
+'
+
+test_expect_success 'pulling from local repo' '
+ (cd local && git pull) &&
+ test_cmp server/file local/file
+'
+
+test_expect_success 'pushing to local repo' '
+ (cd local &&
+ echo content >>file &&
+ git commit -a -m three &&
+ git push) &&
+ compare_refs local HEAD server HEAD
+'
+
+test_expect_success 'fetch new branch' '
+ (cd server &&
+ git reset --hard &&
+ git checkout -b new &&
+ echo content >>file &&
+ git commit -a -m five
+ ) &&
+ (cd local &&
+ git fetch origin new
+ ) &&
+ compare_refs server HEAD local FETCH_HEAD
+'
+
+test_expect_success 'fetch multiple branches' '
+ (cd local &&
+ git fetch
+ ) &&
+ compare_refs server master local refs/remotes/origin/master &&
+ compare_refs server new local refs/remotes/origin/new
+'
+
+test_expect_success 'push when remote has extra refs' '
+ (cd local &&
+ git reset --hard origin/master &&
+ echo content >>file &&
+ git commit -a -m six &&
+ git push
+ ) &&
+ compare_refs local master server master
+'
+
+test_expect_success 'push new branch by name' '
+ (cd local &&
+ git checkout -b new-name &&
+ echo content >>file &&
+ git commit -a -m seven &&
+ git push origin new-name
+ ) &&
+ compare_refs local HEAD server refs/heads/new-name
+'
+
+test_expect_failure 'push new branch with old:new refspec' '
+ (cd local &&
+ git push origin new-name:new-refspec
+ ) &&
+ compare_refs local HEAD server refs/heads/new-refspec
+'
+
+test_expect_success 'cloning without refspec' '
+ GIT_REMOTE_TESTGIT_REFSPEC="" \
+ git clone "testgit::${PWD}/server" local2 &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'pulling without refspecs' '
+ (cd local2 &&
+ git reset --hard &&
+ GIT_REMOTE_TESTGIT_REFSPEC="" git pull) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_failure 'pushing without refspecs' '
+ test_when_finished "(cd local2 && git reset --hard origin)" &&
+ (cd local2 &&
+ echo content >>file &&
+ git commit -a -m ten &&
+ GIT_REMOTE_TESTGIT_REFSPEC="" git push) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'pulling with straight refspec' '
+ (cd local2 &&
+ GIT_REMOTE_TESTGIT_REFSPEC="*:*" git pull) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_failure 'pushing with straight refspec' '
+ test_when_finished "(cd local2 && git reset --hard origin)" &&
+ (cd local2 &&
+ echo content >>file &&
+ git commit -a -m eleven &&
+ GIT_REMOTE_TESTGIT_REFSPEC="*:*" git push) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'pulling without marks' '
+ (cd local2 &&
+ GIT_REMOTE_TESTGIT_NO_MARKS=1 git pull) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_failure 'pushing without marks' '
+ test_when_finished "(cd local2 && git reset --hard origin)" &&
+ (cd local2 &&
+ echo content >>file &&
+ git commit -a -m twelve &&
+ GIT_REMOTE_TESTGIT_NO_MARKS=1 git push) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'push all with existing object' '
+ (cd local &&
+ git branch dup2 master &&
+ git push origin --all
+ ) &&
+ compare_refs local dup2 server dup2
+'
+
+test_expect_success 'push ref with existing object' '
+ (cd local &&
+ git branch dup master &&
+ git push origin dup
+ ) &&
+ compare_refs local dup server dup
+'
+
+test_done
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index f94f0c48e6..3fc3b74c8e 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -3,6 +3,7 @@
test_description='git rev-list --pretty=format test'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
test_tick
test_expect_success 'setup' '
@@ -11,12 +12,24 @@ touch foo && git add foo && git commit -m "added foo" &&
'
# usage: test_format name format_string <expected_output
-test_format() {
+test_format () {
cat >expect.$1
test_expect_success "format $1" "
-git rev-list --pretty=format:'$2' master >output.$1 &&
-test_cmp expect.$1 output.$1
-"
+ git rev-list --pretty=format:'$2' master >output.$1 &&
+ test_cmp expect.$1 output.$1
+ "
+}
+
+# Feed to --format to provide predictable colored sequences.
+AUTO_COLOR='%C(auto,red)foo%C(auto,reset)'
+has_color () {
+ printf '\033[31mfoo\033[m\n' >expect &&
+ test_cmp expect "$1"
+}
+
+has_no_color () {
+ echo foo >expect &&
+ test_cmp expect "$1"
}
test_format percent %%h <<'EOF'
@@ -124,6 +137,48 @@ commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
foo
EOF
+test_expect_success '%C(auto) does not enable color by default' '
+ git log --format=$AUTO_COLOR -1 >actual &&
+ has_no_color actual
+'
+
+test_expect_success '%C(auto) enables colors for color.diff' '
+ git -c color.diff=always log --format=$AUTO_COLOR -1 >actual &&
+ has_color actual
+'
+
+test_expect_success '%C(auto) enables colors for color.ui' '
+ git -c color.ui=always log --format=$AUTO_COLOR -1 >actual &&
+ has_color actual
+'
+
+test_expect_success '%C(auto) respects --color' '
+ git log --format=$AUTO_COLOR -1 --color >actual &&
+ has_color actual
+'
+
+test_expect_success '%C(auto) respects --no-color' '
+ git -c color.ui=always log --format=$AUTO_COLOR -1 --no-color >actual &&
+ has_no_color actual
+'
+
+test_expect_success TTY '%C(auto) respects --color=auto (stdout is tty)' '
+ (
+ TERM=vt100 && export TERM &&
+ test_terminal \
+ git log --format=$AUTO_COLOR -1 --color=auto >actual &&
+ has_color actual
+ )
+'
+
+test_expect_success '%C(auto) respects --color=auto (stdout not tty)' '
+ (
+ TERM=vt100 && export TERM &&
+ git log --format=$AUTO_COLOR -1 --color=auto >actual &&
+ has_no_color actual
+ )
+'
+
cat >commit-msg <<'EOF'
Test printing of complex bodies
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 72e28ee535..3e0e15fb3e 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -676,9 +676,7 @@ test_expect_success 'bisect fails if tree is broken on trial commit' '
check_same()
{
echo "Checking $1 is the same as $2" &&
- git rev-parse "$1" > expected.same &&
- git rev-parse "$2" > expected.actual &&
- test_cmp expected.same expected.actual
+ test_cmp_rev "$1" "$2"
}
test_expect_success 'bisect: --no-checkout - start commit bad' '
diff --git a/t/t6130-pathspec-noglob.sh b/t/t6130-pathspec-noglob.sh
new file mode 100755
index 0000000000..39ef61994f
--- /dev/null
+++ b/t/t6130-pathspec-noglob.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+test_description='test globbing (and noglob) of pathspec limiting'
+. ./test-lib.sh
+
+test_expect_success 'create commits with glob characters' '
+ test_commit unrelated bar &&
+ test_commit vanilla foo &&
+ # insert file "f*" in the commit, but in a way that avoids
+ # the name "f*" in the worktree, because it is not allowed
+ # on Windows (the tests below do not depend on the presence
+ # of the file in the worktree)
+ git update-index --add --cacheinfo 100644 "$(git rev-parse HEAD:foo)" "f*" &&
+ test_tick &&
+ git commit -m star &&
+ test_commit bracket "f[o][o]"
+'
+
+test_expect_success 'vanilla pathspec matches literally' '
+ echo vanilla >expect &&
+ git log --format=%s -- foo >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'star pathspec globs' '
+ cat >expect <<-\EOF &&
+ bracket
+ star
+ vanilla
+ EOF
+ git log --format=%s -- "f*" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'bracket pathspec globs and matches literal brackets' '
+ cat >expect <<-\EOF &&
+ bracket
+ vanilla
+ EOF
+ git log --format=%s -- "f[o][o]" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'no-glob option matches literally (vanilla)' '
+ echo vanilla >expect &&
+ git --literal-pathspecs log --format=%s -- foo >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'no-glob option matches literally (star)' '
+ echo star >expect &&
+ git --literal-pathspecs log --format=%s -- "f*" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'no-glob option matches literally (bracket)' '
+ echo bracket >expect &&
+ git --literal-pathspecs log --format=%s -- "f[o][o]" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'no-glob environment variable works' '
+ echo star >expect &&
+ GIT_LITERAL_PATHSPECS=1 git log --format=%s -- "f*" >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index de7d45352e..2683cba7e3 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -133,6 +133,7 @@ test_expect_success 'submodule add --branch' '
(
cd addtest &&
git submodule add -b initial "$submodurl" submod-branch &&
+ test "initial" = "$(git config -f .gitmodules submodule.submod-branch.branch)" &&
git submodule init
) &&
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index feaec6cdf4..4975ec07ce 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -135,6 +135,37 @@ test_expect_success 'submodule update --force forcibly checks out submodules' '
)
'
+test_expect_success 'submodule update --remote should fetch upstream changes' '
+ (cd submodule &&
+ echo line4 >> file &&
+ git add file &&
+ test_tick &&
+ git commit -m "upstream line4"
+ ) &&
+ (cd super &&
+ git submodule update --remote --force submodule &&
+ cd submodule &&
+ test "$(git log -1 --oneline)" = "$(GIT_DIR=../../submodule/.git git log -1 --oneline)"
+ )
+'
+
+test_expect_success 'local config should override .gitmodules branch' '
+ (cd submodule &&
+ git checkout -b test-branch &&
+ echo line5 >> file &&
+ git add file &&
+ test_tick &&
+ git commit -m "upstream line5" &&
+ git checkout master
+ ) &&
+ (cd super &&
+ git config submodule.submodule.branch test-branch &&
+ git submodule update --remote --force submodule &&
+ cd submodule &&
+ test "$(git log -1 --oneline)" = "$(GIT_DIR=../../submodule/.git git log -1 --oneline test-branch)"
+ )
+'
+
test_expect_success 'submodule update --rebase staying on master' '
(cd super/submodule &&
git checkout master
diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh
index 5b4b694f18..357375151d 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -167,5 +167,19 @@ test_expect_success 'with failing hook (--no-verify)' '
'
+test_expect_success 'with failing hook (merge)' '
+
+ git checkout -B other HEAD@{1} &&
+ echo "more" >> file &&
+ git add file &&
+ rm -f "$HOOK" &&
+ git commit -m other &&
+ write_script "$HOOK" <<-EOF
+ exit 1
+ EOF
+ git checkout - &&
+ test_must_fail git merge other
+
+'
test_done
diff --git a/t/t9020-remote-svn.sh b/t/t9020-remote-svn.sh
index d7be66a1d6..2d2f016f6f 100755
--- a/t/t9020-remote-svn.sh
+++ b/t/t9020-remote-svn.sh
@@ -36,8 +36,8 @@ fi
test_debug '
git --version
- which git
- which svnrdump
+ type git
+ type svnrdump
'
test_expect_success REMOTE_SVN 'simple fetch' '
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 3e821f958b..9320b4f94c 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -303,7 +303,7 @@ 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
+ test_cmp expected output
)
'
@@ -320,7 +320,7 @@ 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
+ test_cmp expected output
)
'
@@ -351,7 +351,7 @@ test_expect_failure 'no exact-ref revisions included' '
(
cd limit-by-paths &&
git fast-export master~2..master~1 > output &&
- test_cmp output expected
+ test_cmp expected output
)
'
@@ -440,4 +440,63 @@ test_expect_success 'fast-export quotes pathnames' '
)
'
+test_expect_success 'test bidirectionality' '
+ >marks-cur &&
+ >marks-new &&
+ git init marks-test &&
+ git fast-export --export-marks=marks-cur --import-marks=marks-cur --branches | \
+ git --git-dir=marks-test/.git fast-import --export-marks=marks-new --import-marks=marks-new &&
+ (cd marks-test &&
+ git reset --hard &&
+ echo Wohlauf > file &&
+ git commit -a -m "back in time") &&
+ git --git-dir=marks-test/.git fast-export --export-marks=marks-new --import-marks=marks-new --branches | \
+ git fast-import --export-marks=marks-cur --import-marks=marks-cur
+'
+
+cat > expected << EOF
+blob
+mark :13
+data 5
+bump
+
+commit refs/heads/master
+mark :14
+author A U Thor <author@example.com> 1112912773 -0700
+committer C O Mitter <committer@example.com> 1112912773 -0700
+data 5
+bump
+from :12
+M 100644 :13 file
+
+EOF
+
+test_expect_success 'avoid uninteresting refs' '
+ > tmp-marks &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks master > /dev/null &&
+ git tag v1.0 &&
+ git branch uninteresting &&
+ echo bump > file &&
+ git commit -a -m bump &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks ^uninteresting ^v1.0 master > actual &&
+ test_cmp expected actual
+'
+
+cat > expected << EOF
+reset refs/heads/master
+from :14
+
+EOF
+
+test_expect_success 'refs are updated even if no commits need to be exported' '
+ > tmp-marks &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks master > /dev/null &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks master > actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t9810-git-p4-rcs.sh b/t/t9810-git-p4-rcs.sh
index 0c2fc3ea1a..34fbc90005 100755
--- a/t/t9810-git-p4-rcs.sh
+++ b/t/t9810-git-p4-rcs.sh
@@ -26,10 +26,8 @@ test_expect_success 'init depot' '
line7
line8
EOF
- cp filek fileko &&
- sed -i "s/Revision/Revision: do not scrub me/" fileko
- cp fileko file_text &&
- sed -i "s/Id/Id: do not scrub me/" file_text
+ sed "s/Revision/Revision: do not scrub me/" <filek >fileko &&
+ sed "s/Id/Id: do not scrub me/" <fileko >file_text &&
p4 add -t text+k filek &&
p4 submit -d "filek" &&
p4 add -t text+ko fileko &&
@@ -88,7 +86,8 @@ test_expect_success 'edit far away from RCS lines' '
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
- sed -i "s/^line7/line7 edit/" filek &&
+ sed "s/^line7/line7 edit/" <filek >filek.tmp &&
+ mv -f filek.tmp filek &&
git commit -m "filek line7 edit" filek &&
git p4 submit &&
scrub_k_check filek
@@ -105,7 +104,8 @@ test_expect_success 'edit near RCS lines' '
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
- sed -i "s/^line4/line4 edit/" filek &&
+ sed "s/^line4/line4 edit/" <filek >filek.tmp &&
+ mv -f filek.tmp filek &&
git commit -m "filek line4 edit" filek &&
git p4 submit &&
scrub_k_check filek
@@ -122,7 +122,8 @@ test_expect_success 'edit keyword lines' '
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
- sed -i "/Revision/d" filek &&
+ sed "/Revision/d" <filek >filek.tmp &&
+ mv -f filek.tmp filek &&
git commit -m "filek remove Revision line" filek &&
git p4 submit &&
scrub_k_check filek
@@ -139,7 +140,8 @@ test_expect_success 'scrub ko files differently' '
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
- sed -i "s/^line4/line4 edit/" fileko &&
+ sed "s/^line4/line4 edit/" <fileko >fileko.tmp &&
+ mv -f fileko.tmp fileko &&
git commit -m "fileko line4 edit" fileko &&
git p4 submit &&
scrub_ko_check fileko &&
@@ -189,12 +191,14 @@ test_expect_success 'do not scrub plain text' '
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
- sed -i "s/^line4/line4 edit/" file_text &&
+ sed "s/^line4/line4 edit/" <file_text >file_text.tmp &&
+ mv -f file_text.tmp file_text &&
git commit -m "file_text line4 edit" file_text &&
(
cd "$cli" &&
p4 open file_text &&
- sed -i "s/^line5/line5 p4 edit/" file_text &&
+ sed "s/^line5/line5 p4 edit/" <file_text >file_text.tmp &&
+ mv -f file_text.tmp file_text &&
p4 submit -d "file5 p4 edit"
) &&
echo s | test_expect_code 1 git p4 submit &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 22a4f8fb64..fa62d010f6 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -602,6 +602,13 @@ test_cmp() {
$GIT_TEST_CMP "$@"
}
+# Tests that its two parameters refer to the same revision
+test_cmp_rev () {
+ git rev-parse --verify "$1" >expect.rev &&
+ git rev-parse --verify "$2" >actual.rev &&
+ test_cmp expect.rev actual.rev
+}
+
# Print a sequence of numbers or letters in increasing order. This is
# similar to GNU seq(1), but the latter might not be available
# everywhere (and does not do letters). It may be used like:
diff --git a/test-wildmatch.c b/test-wildmatch.c
new file mode 100644
index 0000000000..e384c8edb1
--- /dev/null
+++ b/test-wildmatch.c
@@ -0,0 +1,22 @@
+#include "cache.h"
+#include "wildmatch.h"
+
+int main(int argc, char **argv)
+{
+ int i;
+ for (i = 2; i < argc; i++) {
+ if (argv[i][0] == '/')
+ die("Forward slash is not allowed at the beginning of the\n"
+ "pattern because Windows does not like it. Use `XXX/' instead.");
+ else if (!strncmp(argv[i], "XXX/", 4))
+ argv[i] += 3;
+ }
+ if (!strcmp(argv[1], "wildmatch"))
+ return !!wildmatch(argv[3], argv[2], 0);
+ else if (!strcmp(argv[1], "iwildmatch"))
+ return !!wildmatch(argv[3], argv[2], FNM_CASEFOLD);
+ else if (!strcmp(argv[1], "fnmatch"))
+ return !!fnmatch(argv[3], argv[2], FNM_PATHNAME);
+ else
+ return 1;
+}
diff --git a/transport-helper.c b/transport-helper.c
index 4713b69302..965b778cb3 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -661,6 +661,11 @@ static void push_update_ref_status(struct strbuf *buf,
free(msg);
msg = NULL;
}
+ else if (!strcmp(msg, "already exists")) {
+ status = REF_STATUS_REJECT_ALREADY_EXISTS;
+ free(msg);
+ msg = NULL;
+ }
}
if (*ref)
@@ -720,6 +725,7 @@ static int push_refs_with_push(struct transport *transport,
/* Check for statuses set by set_ref_status_for_push() */
switch (ref->status) {
case REF_STATUS_REJECT_NONFASTFORWARD:
+ case REF_STATUS_REJECT_ALREADY_EXISTS:
case REF_STATUS_UPTODATE:
continue;
default:
diff --git a/transport.c b/transport.c
index 9932f402df..2673d273ff 100644
--- a/transport.c
+++ b/transport.c
@@ -659,7 +659,7 @@ static void print_ok_ref_status(struct ref *ref, int porcelain)
const char *msg;
strcpy(quickref, status_abbrev(ref->old_sha1));
- if (ref->nonfastforward) {
+ if (ref->requires_force) {
strcat(quickref, "...");
type = '+';
msg = "forced update";
@@ -695,6 +695,10 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
print_ref_status('!', "[rejected]", ref, ref->peer_ref,
"non-fast-forward", porcelain);
break;
+ case REF_STATUS_REJECT_ALREADY_EXISTS:
+ print_ref_status('!', "[rejected]", ref, ref->peer_ref,
+ "already exists", porcelain);
+ break;
case REF_STATUS_REMOTE_REJECT:
print_ref_status('!', "[remote rejected]", ref,
ref->deletion ? NULL : ref->peer_ref,
@@ -714,7 +718,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
}
void transport_print_push_status(const char *dest, struct ref *refs,
- int verbose, int porcelain, int *nonfastforward)
+ int verbose, int porcelain, unsigned int *reject_reasons)
{
struct ref *ref;
int n = 0;
@@ -733,18 +737,19 @@ void transport_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;
+ *reject_reasons = 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 != NON_FF_HEAD) {
+ if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD) {
if (!strcmp(head, ref->name))
- *nonfastforward = NON_FF_HEAD;
+ *reject_reasons |= REJECT_NON_FF_HEAD;
else
- *nonfastforward = NON_FF_OTHER;
+ *reject_reasons |= REJECT_NON_FF_OTHER;
+ } else if (ref->status == REF_STATUS_REJECT_ALREADY_EXISTS) {
+ *reject_reasons |= REJECT_ALREADY_EXISTS;
}
}
}
@@ -1031,9 +1036,9 @@ static void die_with_unpushed_submodules(struct string_list *needs_pushing)
int transport_push(struct transport *transport,
int refspec_nr, const char **refspec, int flags,
- int *nonfastforward)
+ unsigned int *reject_reasons)
{
- *nonfastforward = 0;
+ *reject_reasons = 0;
transport_verify_remote_names(refspec_nr, refspec);
if (transport->push) {
@@ -1099,7 +1104,7 @@ int transport_push(struct transport *transport,
if (!quiet || err)
transport_print_push_status(transport->url, remote_refs,
verbose | porcelain, porcelain,
- nonfastforward);
+ reject_reasons);
if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
set_upstreams(transport, remote_refs, pretend);
diff --git a/transport.h b/transport.h
index 4a61c0c3f2..bfd2df5823 100644
--- a/transport.h
+++ b/transport.h
@@ -140,11 +140,13 @@ int transport_set_option(struct transport *transport, const char *name,
void transport_set_verbosity(struct transport *transport, int verbosity,
int force_progress);
-#define NON_FF_HEAD 1
-#define NON_FF_OTHER 2
+#define REJECT_NON_FF_HEAD 0x01
+#define REJECT_NON_FF_OTHER 0x02
+#define REJECT_ALREADY_EXISTS 0x04
+
int transport_push(struct transport *connection,
int refspec_nr, const char **refspec, int flags,
- int * nonfastforward);
+ unsigned int * reject_reasons);
const struct ref *transport_get_remote_refs(struct transport *transport);
@@ -170,7 +172,7 @@ void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int v
int transport_refs_pushed(struct ref *ref);
void transport_print_push_status(const char *dest, struct ref *refs,
- int verbose, int porcelain, int *nonfastforward);
+ int verbose, int porcelain, unsigned int *reject_reasons);
typedef void alternate_ref_fn(const struct ref *, void *);
extern void for_each_alternate_ref(alternate_ref_fn, void *);
diff --git a/tree-walk.c b/tree-walk.c
index 3f54c02d76..6e30ef9d04 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -573,6 +573,54 @@ static int match_dir_prefix(const char *base,
}
/*
+ * Perform matching on the leading non-wildcard part of
+ * pathspec. item->nowildcard_len must be greater than zero. Return
+ * non-zero if base is matched.
+ */
+static int match_wildcard_base(const struct pathspec_item *item,
+ const char *base, int baselen,
+ int *matched)
+{
+ const char *match = item->match;
+ /* the wildcard part is not considered in this function */
+ int matchlen = item->nowildcard_len;
+
+ if (baselen) {
+ int dirlen;
+ /*
+ * Return early if base is longer than the
+ * non-wildcard part but it does not match.
+ */
+ if (baselen >= matchlen) {
+ *matched = matchlen;
+ return !strncmp(base, match, matchlen);
+ }
+
+ dirlen = matchlen;
+ while (dirlen && match[dirlen - 1] != '/')
+ dirlen--;
+
+ /*
+ * Return early if base is shorter than the
+ * non-wildcard part but it does not match. Note that
+ * base ends with '/' so we are sure it really matches
+ * directory
+ */
+ if (strncmp(base, match, baselen))
+ return 0;
+ *matched = baselen;
+ } else
+ *matched = 0;
+ /*
+ * we could have checked entry against the non-wildcard part
+ * that is not in base and does similar never_interesting
+ * optimization as in match_entry. For now just be happy with
+ * base comparison.
+ */
+ return entry_interesting;
+}
+
+/*
* Is a tree entry interesting given the pathspec we have?
*
* Pre-condition: either baselen == base_offset (i.e. empty path)
@@ -602,7 +650,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
const struct pathspec_item *item = ps->items+i;
const char *match = item->match;
const char *base_str = base->buf + base_offset;
- int matchlen = item->len;
+ int matchlen = item->len, matched = 0;
if (baselen >= matchlen) {
/* If it doesn't match, move along... */
@@ -626,8 +674,10 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
&never_interesting))
return entry_interesting;
- if (item->use_wildcard) {
- if (!fnmatch(match + baselen, entry->path, 0))
+ if (item->nowildcard_len < item->len) {
+ if (!git_fnmatch(match + baselen, entry->path,
+ item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+ item->nowildcard_len - baselen))
return entry_interesting;
/*
@@ -642,17 +692,34 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
}
match_wildcards:
- if (!item->use_wildcard)
+ if (item->nowildcard_len == item->len)
continue;
+ if (item->nowildcard_len &&
+ !match_wildcard_base(item, base_str, baselen, &matched))
+ return entry_not_interesting;
+
/*
* Concatenate base and entry->path into one and do
* fnmatch() on it.
+ *
+ * While we could avoid concatenation in certain cases
+ * [1], which saves a memcpy and potentially a
+ * realloc, it turns out not worth it. Measurement on
+ * linux-2.6 does not show any clear improvements,
+ * partly because of the nowildcard_len optimization
+ * in git_fnmatch(). Avoid micro-optimizations here.
+ *
+ * [1] if match_wildcard_base() says the base
+ * directory is already matched, we only need to match
+ * the rest, which is shorter so _in theory_ faster.
*/
strbuf_add(base, entry->path, pathlen);
- if (!fnmatch(match, base->buf + base_offset, 0)) {
+ if (!git_fnmatch(match, base->buf + base_offset,
+ item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+ item->nowildcard_len)) {
strbuf_setlen(base, base_offset + baselen);
return entry_interesting;
}
diff --git a/unpack-trees.c b/unpack-trees.c
index 6d9636623a..61acc5e564 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1834,7 +1834,7 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
if (old && same(old, a)) {
int update = 0;
- if (o->reset && !ce_uptodate(old) && !ce_skip_worktree(old)) {
+ if (o->reset && o->update && !ce_uptodate(old) && !ce_skip_worktree(old)) {
struct stat st;
if (lstat(old->name, &st) ||
ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE))
diff --git a/usage.c b/usage.c
index 8eab28113a..40b3de51c7 100644
--- a/usage.c
+++ b/usage.c
@@ -130,6 +130,7 @@ void NORETURN die_errno(const char *fmt, ...)
va_end(params);
}
+#undef error
int error(const char *err, ...)
{
va_list params;
diff --git a/wildmatch.c b/wildmatch.c
new file mode 100644
index 0000000000..2d3ed84364
--- /dev/null
+++ b/wildmatch.c
@@ -0,0 +1,235 @@
+/*
+** Do shell-style pattern matching for ?, \, [], and * characters.
+** It is 8bit clean.
+**
+** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
+** Rich $alz is now <rsalz@bbn.com>.
+**
+** Modified by Wayne Davison to special-case '/' matching, to make '**'
+** work differently than '*', and to fix the character-class code.
+*/
+
+#include "cache.h"
+#include "wildmatch.h"
+
+typedef unsigned char uchar;
+
+/* What character marks an inverted character class? */
+#define NEGATE_CLASS '!'
+#define NEGATE_CLASS2 '^'
+
+#define FALSE 0
+#define TRUE 1
+
+#define CC_EQ(class, len, litmatch) ((len) == sizeof (litmatch)-1 \
+ && *(class) == *(litmatch) \
+ && strncmp((char*)class, litmatch, len) == 0)
+
+#if defined STDC_HEADERS || !defined isascii
+# define ISASCII(c) 1
+#else
+# define ISASCII(c) isascii(c)
+#endif
+
+#ifdef isblank
+# define ISBLANK(c) (ISASCII(c) && isblank(c))
+#else
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+
+#ifdef isgraph
+# define ISGRAPH(c) (ISASCII(c) && isgraph(c))
+#else
+# define ISGRAPH(c) (ISASCII(c) && isprint(c) && !isspace(c))
+#endif
+
+#define ISPRINT(c) (ISASCII(c) && isprint(c))
+#define ISDIGIT(c) (ISASCII(c) && isdigit(c))
+#define ISALNUM(c) (ISASCII(c) && isalnum(c))
+#define ISALPHA(c) (ISASCII(c) && isalpha(c))
+#define ISCNTRL(c) (ISASCII(c) && iscntrl(c))
+#define ISLOWER(c) (ISASCII(c) && islower(c))
+#define ISPUNCT(c) (ISASCII(c) && ispunct(c))
+#define ISSPACE(c) (ISASCII(c) && isspace(c))
+#define ISUPPER(c) (ISASCII(c) && isupper(c))
+#define ISXDIGIT(c) (ISASCII(c) && isxdigit(c))
+
+/* Match pattern "p" against "text" */
+static int dowild(const uchar *p, const uchar *text, int force_lower_case)
+{
+ uchar p_ch;
+ const uchar *pattern = p;
+
+ for ( ; (p_ch = *p) != '\0'; text++, p++) {
+ int matched, match_slash, negated;
+ uchar t_ch, prev_ch;
+ if ((t_ch = *text) == '\0' && p_ch != '*')
+ return ABORT_ALL;
+ if (force_lower_case && ISUPPER(t_ch))
+ t_ch = tolower(t_ch);
+ if (force_lower_case && ISUPPER(p_ch))
+ p_ch = tolower(p_ch);
+ switch (p_ch) {
+ case '\\':
+ /* Literal match with following character. Note that the test
+ * in "default" handles the p[1] == '\0' failure case. */
+ p_ch = *++p;
+ /* FALLTHROUGH */
+ default:
+ if (t_ch != p_ch)
+ return NOMATCH;
+ continue;
+ case '?':
+ /* Match anything but '/'. */
+ if (t_ch == '/')
+ return NOMATCH;
+ continue;
+ case '*':
+ if (*++p == '*') {
+ const uchar *prev_p = p - 2;
+ while (*++p == '*') {}
+ if ((prev_p < pattern || *prev_p == '/') &&
+ (*p == '\0' || *p == '/' ||
+ (p[0] == '\\' && p[1] == '/'))) {
+ /*
+ * Assuming we already match 'foo/' and are at
+ * <star star slash>, just assume it matches
+ * nothing and go ahead match the rest of the
+ * pattern with the remaining string. This
+ * helps make foo/<*><*>/bar (<> because
+ * otherwise it breaks C comment syntax) match
+ * both foo/bar and foo/a/bar.
+ */
+ if (p[0] == '/' &&
+ dowild(p + 1, text, force_lower_case) == MATCH)
+ return MATCH;
+ match_slash = TRUE;
+ } else
+ return ABORT_MALFORMED;
+ } else
+ match_slash = FALSE;
+ if (*p == '\0') {
+ /* Trailing "**" matches everything. Trailing "*" matches
+ * only if there are no more slash characters. */
+ if (!match_slash) {
+ if (strchr((char*)text, '/') != NULL)
+ return NOMATCH;
+ }
+ return MATCH;
+ }
+ while (1) {
+ if (t_ch == '\0')
+ break;
+ if ((matched = dowild(p, text, force_lower_case)) != NOMATCH) {
+ if (!match_slash || matched != ABORT_TO_STARSTAR)
+ return matched;
+ } else if (!match_slash && t_ch == '/')
+ return ABORT_TO_STARSTAR;
+ t_ch = *++text;
+ }
+ return ABORT_ALL;
+ case '[':
+ p_ch = *++p;
+#ifdef NEGATE_CLASS2
+ if (p_ch == NEGATE_CLASS2)
+ p_ch = NEGATE_CLASS;
+#endif
+ /* Assign literal TRUE/FALSE because of "matched" comparison. */
+ negated = p_ch == NEGATE_CLASS? TRUE : FALSE;
+ if (negated) {
+ /* Inverted character class. */
+ p_ch = *++p;
+ }
+ prev_ch = 0;
+ matched = FALSE;
+ do {
+ if (!p_ch)
+ return ABORT_ALL;
+ if (p_ch == '\\') {
+ p_ch = *++p;
+ if (!p_ch)
+ return ABORT_ALL;
+ if (t_ch == p_ch)
+ matched = TRUE;
+ } else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
+ p_ch = *++p;
+ if (p_ch == '\\') {
+ p_ch = *++p;
+ if (!p_ch)
+ return ABORT_ALL;
+ }
+ if (t_ch <= p_ch && t_ch >= prev_ch)
+ matched = TRUE;
+ p_ch = 0; /* This makes "prev_ch" get set to 0. */
+ } else if (p_ch == '[' && p[1] == ':') {
+ const uchar *s;
+ int i;
+ for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {} /*SHARED ITERATOR*/
+ if (!p_ch)
+ return ABORT_ALL;
+ i = p - s - 1;
+ if (i < 0 || p[-1] != ':') {
+ /* Didn't find ":]", so treat like a normal set. */
+ p = s - 2;
+ p_ch = '[';
+ if (t_ch == p_ch)
+ matched = TRUE;
+ continue;
+ }
+ if (CC_EQ(s,i, "alnum")) {
+ if (ISALNUM(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "alpha")) {
+ if (ISALPHA(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "blank")) {
+ if (ISBLANK(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "cntrl")) {
+ if (ISCNTRL(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "digit")) {
+ if (ISDIGIT(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "graph")) {
+ if (ISGRAPH(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "lower")) {
+ if (ISLOWER(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "print")) {
+ if (ISPRINT(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "punct")) {
+ if (ISPUNCT(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "space")) {
+ if (ISSPACE(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "upper")) {
+ if (ISUPPER(t_ch))
+ matched = TRUE;
+ } else if (CC_EQ(s,i, "xdigit")) {
+ if (ISXDIGIT(t_ch))
+ matched = TRUE;
+ } else /* malformed [:class:] string */
+ return ABORT_ALL;
+ p_ch = 0; /* This makes "prev_ch" get set to 0. */
+ } else if (t_ch == p_ch)
+ matched = TRUE;
+ } while (prev_ch = p_ch, (p_ch = *++p) != ']');
+ if (matched == negated || t_ch == '/')
+ return NOMATCH;
+ continue;
+ }
+ }
+
+ return *text ? NOMATCH : MATCH;
+}
+
+/* Match the "pattern" against the "text" string. */
+int wildmatch(const char *pattern, const char *text, int flags)
+{
+ return dowild((const uchar*)pattern, (const uchar*)text,
+ flags & FNM_CASEFOLD ? 1 :0);
+}
diff --git a/wildmatch.h b/wildmatch.h
new file mode 100644
index 0000000000..984a38cdc2
--- /dev/null
+++ b/wildmatch.h
@@ -0,0 +1,9 @@
+/* wildmatch.h */
+
+#define ABORT_MALFORMED 2
+#define NOMATCH 1
+#define MATCH 0
+#define ABORT_ALL -1
+#define ABORT_TO_STARSTAR -2
+
+int wildmatch(const char *pattern, const char *text, int flags);
diff --git a/wrapper.c b/wrapper.c
index a066e2ee9e..bac59d2c41 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -411,11 +411,19 @@ void warn_on_inaccessible(const char *path)
int access_or_warn(const char *path, int mode)
{
int ret = access(path, mode);
- if (ret && errno != ENOENT)
+ if (ret && errno != ENOENT && errno != ENOTDIR)
warn_on_inaccessible(path);
return ret;
}
+int access_or_die(const char *path, int mode)
+{
+ int ret = access(path, mode);
+ if (ret && errno != ENOENT && errno != ENOTDIR)
+ die_errno(_("unable to access '%s'"), path);
+ return ret;
+}
+
struct passwd *xgetpwuid_self(void)
{
struct passwd *pw;