--- /dev/null
+Git v1.7.4.4 Release Notes
+==========================
+
+Fixes since v1.7.4.3
+--------------------
+
+ * Compilation of sha1_file.c on BSD platforms were broken due to our
+ recent use of getrlimit() without including <sys/resource.h>.
+
+ * "git config" did not diagnose incorrect configuration variable names.
+
+ * "git format-patch" did not wrap a long subject line that resulted from
+ rfc2047 encoding.
+
+ * "git instaweb" should work better again with plackup.
+
+ * "git log --max-count=4 -Sfoobar" now shows 4 commits that changes the
+ number of occurrences of string "foobar"; it used to scan only for 4
+ commits and then emitted only matching ones.
+
+ * "git log --first-parent --boundary $c^..$c" segfaulted on a merge.
+
+ * "git pull" into an empty branch should have behaved as if
+ fast-forwarding from emptiness to the version being pulled, with
+ the usual protection against overwriting untracked files.
+
+ * "git submodule" that is run while a merge in the superproject is in
+ conflicted state tried to process each conflicted submodule up to
+ three times.
+
+ * "git status" spent all the effort to notice racily-clean index entries
+ but didn't update the index file to help later operations go faster in
+ some cases.
+
+And other minor fixes and documentation updates.
--- /dev/null
+Git v1.7.4.5 Release Notes
+==========================
+
+This contains only minor documentation fixes accumulated since 1.7.4.4.
-Git v1.7.5 Release Notes (draft)
+Git v1.7.5 Release Notes
========================
Updates since v1.7.4
* Various git-p4 enhancements (in contrib).
- * Various vcs-svn enhancements.
+ * Various vcs-svn, git-svn and gitk enhancements and fixes.
* Various git-gui updates (0.14.0).
negotiation is done. This saves one HTTP RPC, reducing the overall
latency for a trivial fetch.
+ * "git fetch" can be told to recursively fetch submodules on-demand.
+
* "git grep -f <filename>" learned to treat "-" as "read from the
standard input stream".
"tracking" is used as the push.default semantics or there is no remote
configured yet.
+ * A possible value to the "push.default" configuration variable,
+ 'tracking', gained a synonym that more naturally describes what it
+ does, 'upstream'.
+
* "git rerere" learned a new subcommand "remaining" that is similar to
"status" and lists the paths that had conflicts which are known to
rerere, but excludes the paths that have already been marked as
resolved in the index from its output. "git mergetool" has been
updated to use this facility.
- * A possible value to the "push.default" configuration variable,
- 'tracking', gained a synonym that more naturally describes what it
- does, 'upstream'.
-
Also contains various documentation updates.
reachable from the refs in their common alternate object store,
causing it to fetch unnecessary objects (jc/maint-fetch-alt).
- * "git pull" into an empty branch should have behaved as if
- fast-forwarding from emptiness to the version being pulled, with
- the usual protection against overwriting untracked files (need to
- cherry-pick 4b3ffe5).
-
----
-exec >/var/tmp/1
-O=v1.7.5-rc0-99-g8f84c95
-echo O=$(git describe 'master')
-git shortlog --no-merges ^maint ^$O master
+ * "git remote add --mirror" created a configuration that is suitable for
+ doing both a mirror fetch and a mirror push at the same time, which
+ made little sense. We now warn and require the command line to specify
+ either --mirror=fetch or --mirror=push.
If you like, you can put extra tags at the end:
-1. "Reported-by:" is used to to credit someone who found the bug that
+1. "Reported-by:" is used to credit someone who found the bug that
the patch attempts to fix.
2. "Acked-by:" says that the person who is more familiar with the area
the patch attempts to modify liked the patch.
Just make sure to disable line wrapping in the email client (GMail web
interface will line wrap no matter what, so you need to use a real
IMAP client).
-
Set the path to the root of the working tree.
This can be overridden by the GIT_WORK_TREE environment
variable and the '--work-tree' command line option.
- The value can an absolute path or relative to the path to
+ The value can be an absolute path or relative to the path to
the .git directory, which is either specified by --git-dir
or GIT_DIR, or automatically discovered.
If --git-dir or GIT_DIR is specified but none of
be delta compressed, but larger binary media files won't be.
+
Common unit suffixes of 'k', 'm', or 'g' are supported.
-+
-Currently only linkgit:git-fast-import[1] honors this setting.
core.excludesfile::
In addition to '.gitignore' (per-directory) and
characters are *ignorable* whitespace.
fetch.recurseSubmodules::
- A boolean value which changes the behavior for fetch and pull, the
- default is to not recursively fetch populated submodules unless
- configured otherwise.
+ This option can be either set to a boolean value or to 'on-demand'.
+ Setting it to a boolean changes the behavior of fetch and pull to
+ unconditionally recurse into submodules when set to true or to not
+ recurse at all when set to false. When set to 'on-demand' (the default
+ value), fetch and pull will only recurse into a populated submodule
+ when its superproject retrieves a commit that updates the submodule's
+ reference.
fetch.unpackLimit::
If the number of objects fetched over the git native
linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
submodule.<name>.fetchRecurseSubmodules::
- This option can be used to enable/disable recursive fetching of this
+ This option can be used to control recursive fetching of this
submodule. It can be overridden by using the --[no-]recurse-submodules
command line option to "git fetch" and "git pull".
This setting will override that from in the linkgit:gitmodules[5]
specified with the remote.<name>.tagopt setting. See
linkgit:git-config[1].
---[no-]recurse-submodules::
- This option controls if new commits of all populated submodules should
- be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
+--recurse-submodules[=yes|on-demand|no]::
+ This option controls if and under what conditions new commits of
+ populated submodules should be fetched too. It can be used as a
+ boolean option to completely disable recursion when set to 'no' or to
+ unconditionally recurse into all populated submodules when set to
+ 'yes', which is the default when this option is used without any
+ value. Use 'on-demand' to only recurse into a populated submodule
+ when the superproject retrieves a commit that updates the submodule's
+ reference to a commit that isn't already in the local submodule
+ clone.
+
+--no-recurse-submodules::
+ Disable recursive fetching of submodules (this has the same effect as
+ using the '--recurse-submodules=no' option).
--submodule-prefix=<path>::
Prepend <path> to paths printed in informative messages
such as "Fetching submodule foo". This option is used
internally when recursing over submodules.
+
+--recurse-submodules-default=[yes|on-demand]::
+ This option is used internally to temporarily provide a
+ non-negative default value for the --recurse-submodules
+ option. All other methods of configuring fetch's submodule
+ recursion (such as settings in linkgit:gitmodules[5] and
+ linkgit:git-config[1]) override this option, as does
+ specifying --[no-]recurse-submodules directly.
endif::git-pull[]
-u::
tar archive entries. The default is 0002, which turns off the
world write bit. The special value "user" indicates that the
archiving user's umask will be used instead. See umask(2) for
- details.
+ details. If `--remote` is used then only the configuration of
+ the remote repository takes effect.
ATTRIBUTES
----------
those missing tags. If the other end has tags that point at
branches you are not interested in, you will not get them.
-'git fetch' can fetch from either a single named repository, or
+'git fetch' can fetch from either a single named repository,
or from several repositories at once if <group> is given and
there is a remotes.<group> entry in the configuration file.
(See linkgit:git-config[1]).
because it is prefixed with a plus sign; `tmp` will not be.
+BUGS
+----
+Using --recurse-submodules can only fetch new commits in already checked
+out submodules right now. When e.g. upstream added a new submodule in the
+just fetched commits of the superproject the submodule itself can not be
+fetched, making it impossible to check out that submodule later without
+having to do a fetch again. This is expected to be fixed in a future git
+version.
+
SEE ALSO
--------
linkgit:git-pull[1]
--honor-pack-keep::
This flag causes an object already in a local pack that
- has a .keep file to be ignored, even if it it would have
+ has a .keep file to be ignored, even if it would have
otherwise been packed.
--incremental::
--verbose::
Pass --verbose to git-fetch and git-merge.
---[no-]recurse-submodules::
+--[no-]recurse-submodules[=yes|on-demand|no]::
This option controls if new commits of all populated submodules should
be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
That might be necessary to get the data needed for merging submodule
would want to start over, you can recover with 'git reset'.
+BUGS
+----
+Using --recurse-submodules can only fetch new commits in already checked
+out submodules right now. When e.g. upstream added a new submodule in the
+just fetched commits of the superproject the submodule itself can not be
+fetched, making it impossible to check out that submodule later without
+having to do a fetch again. This is expected to be fixed in a future git
+version.
+
SEE ALSO
--------
linkgit:git-fetch[1], linkgit:git-merge[1], linkgit:git-config[1]
--------
[verse]
'git remote' [-v | --verbose]
-'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror] <name> <url>
+'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>
'git remote rename' <old> <new>
'git remote rm' <name>
'git remote set-head' <name> (-a | -d | <branch>)
With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
up to point at remote's `<master>` branch. See also the set-head command.
+
-In mirror mode, enabled with `\--mirror`, the refs will not be stored
-in the 'refs/remotes/' namespace, but in 'refs/heads/'. This option
-only makes sense in bare repositories. If a remote uses mirror
-mode, furthermore, `git push` will always behave as if `\--mirror`
-was passed.
+When a fetch mirror is created with `\--mirror=fetch`, the refs will not
+be stored in the 'refs/remotes/' namespace, but rather everything in
+'refs/' on the remote will be directly mirrored into 'refs/' in the
+local repository. This option only makes sense in bare repositories,
+because a fetch would overwrite any local commits.
++
+When a push mirror is created with `\--mirror=push`, then `git push`
+will always behave as if `\--mirror` was passed.
'rename'::
currently checked out commit for each submodule, along with the
submodule path and the output of 'git describe' for the
SHA-1. Each SHA-1 will be prefixed with `-` if the submodule is not
- initialized and `+` if the currently checked out submodule commit
+ initialized, `+` if the currently checked out submodule commit
does not match the SHA-1 found in the index of the containing
- repository. This command is the default command for 'git submodule'.
+ repository and `U` if the submodule has merge conflicts.
+ This command is the default command for 'git submodule'.
+
If '--recursive' is specified, this command will recurse into nested
submodules, and show their status as well.
Using this option for any other purpose (don't ask) is very strongly
discouraged.
+--mergeinfo=<mergeinfo>;;
+ Add the given merge information during the dcommit
+ (e.g. `--mergeinfo="/branches/foo:1-10"`). All svn server versions can
+ store this information (as a property), and svn clients starting from
+ version 1.5 can make use of it. 'git svn' currently does not use it
+ and does not set it automatically.
+
'branch'::
Create a branch in the SVN repository.
Empty directories are automatically recreated when using
"git svn clone" and "git svn rebase", so "mkdirs" is intended
for use after commands like "git checkout" or "git reset".
+ (See the svn-remote.<name>.automkdirs config file option for
+ more information.)
'commit-diff'::
Commits the diff of two tree-ish arguments from the
where the original UUID is not available via either useSvmProps
or useSvnsyncProps.
+svn-remote.<name>.pushurl::
+
+ Similar to git's 'remote.<name>.pushurl', this key is designed
+ to be used in cases where 'url' points to an SVN repository
+ via a read-only transport, to provide an alternate read/write
+ transport. It is assumed that both keys point to the same
+ repository. Unlike 'commiturl', 'pushurl' is a base path. If
+ either 'commiturl' or 'pushurl' could be used, 'commiturl'
+ takes precedence.
+
svn.brokenSymlinkWorkaround::
This disables potentially expensive checks to workaround
broken symlinks checked into SVN by broken clients. Set this
locales to avoid corrupted file names with non-ASCII characters.
Valid encodings are the ones supported by Perl's Encode module.
+svn-remote.<name>.automkdirs::
+ Normally, the "git svn clone" and "git svn rebase" commands
+ attempt to recreate empty directories that are in the
+ Subversion repository. If this option is set to "false", then
+ empty directories will only be created if the "git svn mkdirs"
+ command is run explicitly. If unset, 'git svn' assumes this
+ option to be "true".
+
Since the noMetadata, rewriteRoot, rewriteUUID, useSvnsyncProps and useSvmProps
options all affect the metadata generated and used by 'git svn'; they
*must* be set in the configuration file before any history is imported
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.7.4.3/git.html[documentation for release 1.7.4.3]
+* link:v1.7.5/git.html[documentation for release 1.7.5]
* release notes for
+ link:RelNotes/1.7.5.txt[1.7.5].
+
+* link:v1.7.4.5/git.html[documentation for release 1.7.4.5]
+
+* release notes for
+ link:RelNotes/1.7.4.5.txt[1.7.4.5],
+ link:RelNotes/1.7.4.4.txt[1.7.4.4],
link:RelNotes/1.7.4.3.txt[1.7.4.3],
link:RelNotes/1.7.4.2.txt[1.7.4.2],
link:RelNotes/1.7.4.1.txt[1.7.4.1],
contents of <old|new>,
<old|new>-hex:: are the 40-hexdigit SHA1 hashes,
<old|new>-mode:: are the octal representation of the file modes.
-
+
The file parameters can point at the user's working file
(e.g. `new-file` in "git-diff-files"), `/dev/null` (e.g. `old-file`
the '--merge' or '--rebase' options.
submodule.<name>.fetchRecurseSubmodules::
- This option can be used to enable/disable recursive fetching of this
+ This option can be used to control recursive fetching of this
submodule. If this option is also present in the submodules entry in
.git/config of the superproject, the setting there will override the
one found in .gitmodules.
Both settings can be overridden on the command line by using the
- "--[no-]recurse-submodules" option to "git fetch" and "git pull"..
+ "--[no-]recurse-submodules" option to "git fetch" and "git pull".
submodule.<name>.ignore::
Defines under what circumstances "git status" and the diff family show
+
For example, if you have two branches, `A` and `B`, a usual way
to list all commits on only one side of them is with
-`--left-right`, like the example above in the description of
-that option. It however shows the commits that were cherry-picked
+`--left-right` (see the example below in the description of
+the `--left-right` option). It however shows the commits that were cherry-picked
from the other branch (for example, "3rd on b" may be cherry-picked
from branch A). With this option, such pairs of commits are
excluded from the output.
SPECIFYING REVISIONS
--------------------
-A revision parameter typically, but not necessarily, names a
-commit object. They use what is called an 'extended SHA1'
+A revision parameter '<rev>' typically, but not necessarily, names a
+commit object. It uses what is called an 'extended SHA1'
syntax. Here are various ways to spell object names. The
-ones listed near the end of this list are to name trees and
+ones listed near the end of this list name trees and
blobs contained in a commit.
-* The full SHA1 object name (40-byte hexadecimal string), or
- a substring of such that is unique within the repository.
+'<sha1>', e.g. 'dae86e1950b1277e545cee180551750029cfe735', 'dae86e'::
+ The full SHA1 object name (40-byte hexadecimal string), or
+ a leading substring that is unique within the repository.
E.g. dae86e1950b1277e545cee180551750029cfe735 and dae86e both
- name the same commit object if there are no other object in
+ name the same commit object if there is no other object in
your repository whose object name starts with dae86e.
-* An output from 'git describe'; i.e. a closest tag, optionally
+'<describeOutput>', e.g. 'v1.7.4.2-679-g3bee7fb'::
+ Output from `git describe`; i.e. a closest tag, optionally
followed by a dash and a number of commits, followed by a dash, a
- `g`, and an abbreviated object name.
+ 'g', and an abbreviated object name.
-* A symbolic ref name. E.g. 'master' typically means the commit
- object referenced by refs/heads/master. If you
- happen to have both heads/master and tags/master, you can
+'<refname>', e.g. 'master', 'heads/master', 'refs/heads/master'::
+ A symbolic ref name. E.g. 'master' typically means the commit
+ object referenced by 'refs/heads/master'. If you
+ happen to have both 'heads/master' and 'tags/master', you can
explicitly say 'heads/master' to tell git which one you mean.
- When ambiguous, a `<name>` is disambiguated by taking the
+ When ambiguous, a '<name>' is disambiguated by taking the
first match in the following rules:
- . if `$GIT_DIR/<name>` exists, that is what you mean (this is usually
- useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD`, `MERGE_HEAD`
- and `CHERRY_PICK_HEAD`);
+ . If '$GIT_DIR/<name>' exists, that is what you mean (this is usually
+ useful only for 'HEAD', 'FETCH_HEAD', 'ORIG_HEAD', 'MERGE_HEAD'
+ and 'CHERRY_PICK_HEAD');
- . otherwise, `refs/<name>` if exists;
+ . otherwise, 'refs/<name>' if it exists;
- . otherwise, `refs/tags/<name>` if exists;
+ . otherwise, 'refs/tags/<refname>' if it exists;
- . otherwise, `refs/heads/<name>` if exists;
+ . otherwise, 'refs/heads/<name>' if it exists;
- . otherwise, `refs/remotes/<name>` if exists;
+ . otherwise, 'refs/remotes/<name>' if it exists;
- . otherwise, `refs/remotes/<name>/HEAD` if exists.
+ . otherwise, 'refs/remotes/<name>/HEAD' if it exists.
+
-HEAD names the commit your changes in the working tree is based on.
-FETCH_HEAD records the branch you fetched from a remote repository
-with your last 'git fetch' invocation.
-ORIG_HEAD is created by commands that moves your HEAD in a drastic
-way, to record the position of the HEAD before their operation, so that
-you can change the tip of the branch back to the state before you ran
-them easily.
-MERGE_HEAD records the commit(s) you are merging into your branch
-when you run 'git merge'.
-CHERRY_PICK_HEAD records the commit you are cherry-picking
-when you run 'git cherry-pick'.
+'HEAD' names the commit on which you based the changes in the working tree.
+'FETCH_HEAD' records the branch which you fetched from a remote repository
+with your last `git fetch` invocation.
+'ORIG_HEAD' is created by commands that move your 'HEAD' in a drastic
+way, to record the position of the 'HEAD' before their operation, so that
+you can easily change the tip of the branch back to the state before you ran
+them.
+'MERGE_HEAD' records the commit(s) which you are merging into your branch
+when you run `git merge`.
+'CHERRY_PICK_HEAD' records the commit which you are cherry-picking
+when you run `git cherry-pick`.
+
-Note that any of the `refs/*` cases above may come either from
-the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.
+Note that any of the 'refs/*' cases above may come either from
+the '$GIT_DIR/refs' directory or from the '$GIT_DIR/packed-refs' file.
-* A ref followed by the suffix '@' with a date specification
+'<refname>@\{<date>\}', e.g. 'master@\{yesterday\}', 'HEAD@\{5 minutes ago\}'::
+ A ref followed by the suffix '@' with a date specification
enclosed in a brace
pair (e.g. '\{yesterday\}', '\{1 month 2 weeks 3 days 1 hour 1
- second ago\}' or '\{1979-02-26 18:30:00\}') to specify the value
+ second ago\}' or '\{1979-02-26 18:30:00\}') specifies the value
of the ref at a prior point in time. This suffix may only be
used immediately following a ref name and the ref must have an
- existing log ($GIT_DIR/logs/<ref>). Note that this looks up the state
+ existing log ('$GIT_DIR/logs/<ref>'). Note that this looks up the state
of your *local* ref at a given time; e.g., what was in your local
- `master` branch last week. If you want to look at commits made during
- certain times, see `--since` and `--until`.
+ 'master' branch last week. If you want to look at commits made during
+ certain times, see '--since' and '--until'.
-* A ref followed by the suffix '@' with an ordinal specification
- enclosed in a brace pair (e.g. '\{1\}', '\{15\}') to specify
+'<refname>@\{<n>\}', e.g. 'master@\{1\}'::
+ A ref followed by the suffix '@' with an ordinal specification
+ enclosed in a brace pair (e.g. '\{1\}', '\{15\}') specifies
the n-th prior value of that ref. For example 'master@\{1\}'
is the immediate prior value of 'master' while 'master@\{5\}'
is the 5th prior value of 'master'. This suffix may only be used
immediately following a ref name and the ref must have an existing
- log ($GIT_DIR/logs/<ref>).
+ log ('$GIT_DIR/logs/<refname>').
-* You can use the '@' construct with an empty ref part to get at a
- reflog of the current branch. For example, if you are on the
- branch 'blabla', then '@\{1\}' means the same as 'blabla@\{1\}'.
+'@\{<n>\}', e.g. '@\{1\}'::
+ You can use the '@' construct with an empty ref part to get at a
+ reflog entry of the current branch. For example, if you are on
+ branch 'blabla' then '@\{1\}' means the same as 'blabla@\{1\}'.
-* The special construct '@\{-<n>\}' means the <n>th branch checked out
+'@\{-<n>\}', e.g. '@\{-1\}'::
+ The construct '@\{-<n>\}' means the <n>th branch checked out
before the current one.
-* The suffix '@\{upstream\}' to a ref (short form 'ref@\{u\}') refers to
- the branch the ref is set to build on top of. Missing ref defaults
+'<refname>@\{upstream\}', e.g. 'master@\{upstream\}', '@\{u\}'::
+ The suffix '@\{upstream\}' to a ref (short form '<refname>@\{u\}') refers to
+ the branch the ref is set to build on top of. A missing ref defaults
to the current branch.
-* A suffix '{caret}' to a revision parameter (e.g. 'HEAD{caret}') means the first parent of
+'<rev>{caret}', e.g. 'HEAD{caret}, v1.5.1{caret}0'::
+ A suffix '{caret}' to a revision parameter means the first parent of
that commit object. '{caret}<n>' means the <n>th parent (i.e.
- 'rev{caret}'
- is equivalent to 'rev{caret}1'). As a special rule,
- 'rev{caret}0' means the commit itself and is used when 'rev' is the
+ '<rev>{caret}'
+ is equivalent to '<rev>{caret}1'). As a special rule,
+ '<rev>{caret}0' means the commit itself and is used when '<rev>' is the
object name of a tag object that refers to a commit object.
-* A suffix '{tilde}<n>' to a revision parameter means the commit
+'<rev>{tilde}<n>', e.g. 'master{tilde}3'::
+ A suffix '{tilde}<n>' to a revision parameter means the commit
object that is the <n>th generation grand-parent of the named
- commit object, following only the first parent. I.e. rev~3 is
- equivalent to rev{caret}{caret}{caret} which is equivalent to
- rev{caret}1{caret}1{caret}1. See below for a illustration of
+ commit object, following only the first parents. I.e. '<rev>{tilde}3' is
+ equivalent to '<rev>{caret}{caret}{caret}' which is equivalent to
+ '<rev>{caret}1{caret}1{caret}1'. See below for an illustration of
the usage of this form.
-* A suffix '{caret}' followed by an object type name enclosed in
- brace pair (e.g. `v0.99.8{caret}\{commit\}`) means the object
+'<rev>{caret}\{<type>\}', e.g. 'v0.99.8{caret}\{commit\}'::
+ A suffix '{caret}' followed by an object type name enclosed in
+ brace pair means the object
could be a tag, and dereference the tag recursively until an
object of that type is found or the object cannot be
- dereferenced anymore (in which case, barf). `rev{caret}0`
- introduced earlier is a short-hand for `rev{caret}\{commit\}`.
+ dereferenced anymore (in which case, barf). '<rev>{caret}0'
+ is a short-hand for '<rev>{caret}\{commit\}'.
-* A suffix '{caret}' followed by an empty brace pair
- (e.g. `v0.99.8{caret}\{\}`) means the object could be a tag,
+'<rev>{caret}\{\}', e.g. 'v0.99.8{caret}\{\}'::
+ A suffix '{caret}' followed by an empty brace pair
+ means the object could be a tag,
and dereference the tag recursively until a non-tag object is
found.
-* A suffix '{caret}' to a revision parameter followed by a brace
- pair that contains a text led by a slash (e.g. `HEAD^{/fix nasty bug}`):
- this is the same as `:/fix nasty bug` syntax below except that
+'<rev>{caret}\{/<text>\}', e.g. 'HEAD^{/fix nasty bug}'::
+ A suffix '{caret}' to a revision parameter, followed by a brace
+ pair that contains a text led by a slash,
+ is the same as the ':/fix nasty bug' syntax below except that
it returns the youngest matching commit which is reachable from
- the ref before '{caret}'.
+ the '<rev>' before '{caret}'.
-* A colon, followed by a slash, followed by a text (e.g. `:/fix nasty bug`): this names
+':/<text>', e.g. ':/fix nasty bug'::
+ A colon, followed by a slash, followed by a text, names
a commit whose commit message matches the specified regular expression.
This name returns the youngest matching commit which is
reachable from any ref. If the commit message starts with a
- '!', you have to repeat that; the special sequence ':/!',
- followed by something else than '!' is reserved for now.
+ '!' you have to repeat that; the special sequence ':/!',
+ followed by something else than '!', is reserved for now.
The regular expression can match any part of the commit message. To
- match messages starting with a string, one can use e.g. `:/^foo`.
+ match messages starting with a string, one can use e.g. ':/^foo'.
-* A suffix ':' followed by a path (e.g. `HEAD:README`); this names the blob or tree
+'<rev>:<path>', e.g. 'HEAD:README', ':README', 'master:./README'::
+ A suffix ':' followed by a path names the blob or tree
at the given path in the tree-ish object named by the part
before the colon.
- ':path' (with an empty part before the colon, e.g. `:README`)
+ ':path' (with an empty part before the colon)
is a special case of the syntax described next: content
recorded in the index at the given path.
- A path starting with './' or '../' is relative to current working directory.
- The given path will be converted to be relative to working tree's root directory.
+ A path starting with './' or '../' is relative to the current working directory.
+ The given path will be converted to be relative to the working tree's root directory.
This is most useful to address a blob or tree from a commit or tree that has
- the same tree structure with the working tree.
+ the same tree structure as the working tree.
-* A colon, optionally followed by a stage number (0 to 3) and a
- colon, followed by a path (e.g. `:0:README`); this names a blob object in the
- index at the given path. Missing stage number (and the colon
- that follows it, e.g. `:README`) names a stage 0 entry. During a merge, stage
+':<n>:<path>', e.g. ':0:README', ':README'::
+ A colon, optionally followed by a stage number (0 to 3) and a
+ colon, followed by a path, names a blob object in the
+ index at the given path. A missing stage number (and the colon
+ that follows it) names a stage 0 entry. During a merge, stage
1 is the common ancestor, stage 2 is the target branch's version
(typically the current branch), and stage 3 is the version from
- the branch being merged.
+ the branch which is being merged.
Here is an illustration, by Jon Loeliger. Both commit nodes B
and C are parents of commit node A. Parent commits are ordered
SPECIFYING RANGES
-----------------
-History traversing commands such as 'git log' operate on a set
+History traversing commands such as `git log` operate on a set
of commits, not just a single commit. To these commands,
specifying a single revision with the notation described in the
previous section means the set of commits reachable from that
commit, following the commit ancestry chain.
-To exclude commits reachable from a commit, a prefix `{caret}`
-notation is used. E.g. `{caret}r1 r2` means commits reachable
-from `r2` but exclude the ones reachable from `r1`.
+To exclude commits reachable from a commit, a prefix '{caret}'
+notation is used. E.g. '{caret}r1 r2' means commits reachable
+from 'r2' but exclude the ones reachable from 'r1'.
This set operation appears so often that there is a shorthand
-for it. When you have two commits `r1` and `r2` (named according
+for it. When you have two commits 'r1' and 'r2' (named according
to the syntax explained in SPECIFYING REVISIONS above), you can ask
for commits that are reachable from r2 excluding those that are reachable
-from r1 by `{caret}r1 r2` and it can be written as `r1..r2`.
+from r1 by '{caret}r1 r2' and it can be written as 'r1..r2'.
-A similar notation `r1\...r2` is called symmetric difference
-of `r1` and `r2` and is defined as
-`r1 r2 --not $(git merge-base --all r1 r2)`.
+A similar notation 'r1\...r2' is called symmetric difference
+of 'r1' and 'r2' and is defined as
+'r1 r2 --not $(git merge-base --all r1 r2)'.
It is the set of commits that are reachable from either one of
-`r1` or `r2` but not from both.
+'r1' or 'r2' but not from both.
Two other shorthands for naming a set that is formed by a commit
-and its parent commits exist. The `r1{caret}@` notation means all
-parents of `r1`. `r1{caret}!` includes commit `r1` but excludes
+and its parent commits exist. The 'r1{caret}@' notation means all
+parents of 'r1'. 'r1{caret}!' includes commit 'r1' but excludes
all of its parents.
Here are a handful of examples:
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.5-rc0
+DEF_VER=v1.7.5
LF='
'
--add-comments \
--msgid-bugs-address="Git Mailing List <git@vger.kernel.org>" \
--from-code=UTF-8
-XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --keyword=_ --keyword=N_ --language=C
+XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
+ --keyword=_ --keyword=N_ --keyword="Q_:1,2"
LOCALIZED_C := $(C_OBJ:o=c)
po/git.pot: $(LOCALIZED_C)
TAGS_SET = 2
};
-enum {
- RECURSE_SUBMODULES_OFF = 0,
- RECURSE_SUBMODULES_DEFAULT = 1,
- RECURSE_SUBMODULES_ON = 2
-};
-
static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;
static int progress, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static int tags = TAGS_DEFAULT;
static struct strbuf default_rla = STRBUF_INIT;
static struct transport *transport;
static const char *submodule_prefix = "";
+static const char *recurse_submodules_default;
+
+static int option_parse_recurse_submodules(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset) {
+ recurse_submodules = RECURSE_SUBMODULES_OFF;
+ } else {
+ if (arg)
+ recurse_submodules = parse_fetch_recurse_submodules_arg(opt->long_name, arg);
+ else
+ recurse_submodules = RECURSE_SUBMODULES_ON;
+ }
+ return 0;
+}
static struct option builtin_fetch_options[] = {
OPT__VERBOSITY(&verbosity),
"do not fetch all tags (--no-tags)", TAGS_UNSET),
OPT_BOOLEAN('p', "prune", &prune,
"prune remote-tracking branches no longer on remote"),
- OPT_SET_INT(0, "recurse-submodules", &recurse_submodules,
+ { OPTION_CALLBACK, 0, "recurse-submodules", NULL, "on-demand",
"control recursive fetching of submodules",
- RECURSE_SUBMODULES_ON),
+ PARSE_OPT_OPTARG, option_parse_recurse_submodules },
OPT_BOOLEAN(0, "dry-run", &dry_run,
"dry run"),
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
"deepen history of shallow clone"),
{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "dir",
"prepend this to submodule path output", PARSE_OPT_HIDDEN },
+ { OPTION_STRING, 0, "recurse-submodules-default",
+ &recurse_submodules_default, NULL,
+ "default mode for recursion", PARSE_OPT_HIDDEN },
OPT_END()
};
else {
msg = "storing head";
what = _("[new branch]");
+ if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+ (recurse_submodules != RECURSE_SUBMODULES_ON))
+ check_for_new_submodule_commits(ref->new_sha1);
}
r = s_update_ref(msg, ref, 0);
strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcat(quickref, "..");
strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
+ if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+ (recurse_submodules != RECURSE_SUBMODULES_ON))
+ check_for_new_submodule_commits(ref->new_sha1);
r = s_update_ref("fast-forward", ref, 1);
sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ',
TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcat(quickref, "...");
strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
+ if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+ (recurse_submodules != RECURSE_SUBMODULES_ON))
+ check_for_new_submodule_commits(ref->new_sha1);
r = s_update_ref("forced-update", ref, 1);
sprintf(display, "%c %-*s %-*s -> %s (%s)", r ? '!' : '+',
TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
argv[(*argc)++] = "--keep";
if (recurse_submodules == RECURSE_SUBMODULES_ON)
argv[(*argc)++] = "--recurse-submodules";
+ else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
+ argv[(*argc)++] = "--recurse-submodules=on-demand";
if (verbosity >= 2)
argv[(*argc)++] = "-v";
if (verbosity >= 1)
if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
const char *options[10];
int num_options = 0;
- /* Set recursion as default when we already are recursing */
- if (submodule_prefix[0])
- set_config_fetch_recurse_submodules(1);
+ if (recurse_submodules_default) {
+ int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default);
+ set_config_fetch_recurse_submodules(arg);
+ }
gitmodules_config();
git_config(submodule_config, NULL);
add_options_to_argv(&num_options, options);
result = fetch_populated_submodules(num_options, options,
submodule_prefix,
- recurse_submodules == RECURSE_SUBMODULES_ON,
+ recurse_submodules,
verbosity < 0);
}
return -1;
}
-static void cmd_log_init(int argc, const char **argv, const char *prefix,
- struct rev_info *rev, struct setup_revision_opt *opt)
+static void cmd_log_init_defaults(struct rev_info *rev)
{
- int i;
- int decoration_given = 0;
- struct userformat_want w;
-
rev->abbrev = DEFAULT_ABBREV;
rev->commit_format = CMIT_FMT_DEFAULT;
if (fmt_pretty)
if (default_date_mode)
rev->date_mode = parse_date_format(default_date_mode);
+}
+static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
+ struct rev_info *rev, struct setup_revision_opt *opt)
+{
+ int i;
+ int decoration_given = 0;
+ struct userformat_want w;
/*
* Check for -h before setup_revisions(), or "git log -h" will
* fail when run without a git directory.
setup_pager();
}
+static void cmd_log_init(int argc, const char **argv, const char *prefix,
+ struct rev_info *rev, struct setup_revision_opt *opt)
+{
+ cmd_log_init_defaults(rev);
+ cmd_log_init_finish(argc, argv, prefix, rev, opt);
+}
+
/*
* This gives a rough estimate for how many commits we
* will print out in the list.
rev.verbose_header = 1;
memset(&opt, 0, sizeof(opt));
opt.def = "HEAD";
- cmd_log_init(argc, argv, prefix, &rev, &opt);
-
- /*
- * This means that we override whatever commit format the user gave
- * on the cmd line. Sad, but cmd_log_init() currently doesn't
- * allow us to set a different default.
- */
+ cmd_log_init_defaults(&rev);
rev.commit_format = CMIT_FMT_ONELINE;
rev.use_terminator = 1;
rev.always_show_header = 1;
+ cmd_log_init_finish(argc, argv, prefix, &rev, &opt);
return cmd_log_walk(&rev);
}
sorted_by_offset[i] = objects + i;
qsort(sorted_by_offset, nr_objects, sizeof(*sorted_by_offset), pack_offset_sort);
- for (i = 0; i < nr_objects; i++)
- check_object(sorted_by_offset[i]);
+ for (i = 0; i < nr_objects; i++) {
+ struct object_entry *entry = sorted_by_offset[i];
+ check_object(entry);
+ if (big_file_threshold <= entry->size)
+ entry->no_try_delta = 1;
+ }
free(sorted_by_offset);
}
static const char * const builtin_remote_usage[] = {
"git remote [-v | --verbose]",
- "git remote add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>",
+ "git remote add [-t <branch>] [-m <master>] [-f] [--mirror=<fetch|push>] <name> <url>",
"git remote rename <old> <new>",
"git remote rm <name>",
"git remote set-head <name> (-a | -d | <branch>)",
TAGS_SET = 2
};
+#define MIRROR_NONE 0
+#define MIRROR_FETCH 1
+#define MIRROR_PUSH 2
+#define MIRROR_BOTH (MIRROR_FETCH|MIRROR_PUSH)
+
static int add_branch(const char *key, const char *branchname,
const char *remotename, int mirror, struct strbuf *tmp)
{
return git_config_set_multivar(key, tmp->buf, "^$", 0);
}
+static const char mirror_advice[] =
+"--mirror is dangerous and deprecated; please\n"
+"\t use --mirror=fetch or --mirror=push instead";
+
+static int parse_mirror_opt(const struct option *opt, const char *arg, int not)
+{
+ unsigned *mirror = opt->value;
+ if (not)
+ *mirror = MIRROR_NONE;
+ else if (!arg) {
+ warning("%s", mirror_advice);
+ *mirror = MIRROR_BOTH;
+ }
+ else if (!strcmp(arg, "fetch"))
+ *mirror = MIRROR_FETCH;
+ else if (!strcmp(arg, "push"))
+ *mirror = MIRROR_PUSH;
+ else
+ return error("unknown mirror argument: %s", arg);
+ return 0;
+}
+
static int add(int argc, const char **argv)
{
- int fetch = 0, mirror = 0, fetch_tags = TAGS_DEFAULT;
+ int fetch = 0, fetch_tags = TAGS_DEFAULT;
+ unsigned mirror = MIRROR_NONE;
struct string_list track = STRING_LIST_INIT_NODUP;
const char *master = NULL;
struct remote *remote;
OPT_CALLBACK('t', "track", &track, "branch",
"branch(es) to track", opt_parse_track),
OPT_STRING('m', "master", &master, "branch", "master branch"),
- OPT_BOOLEAN(0, "mirror", &mirror, "no separate remotes"),
+ { OPTION_CALLBACK, 0, "mirror", &mirror, "push|fetch",
+ "set up remote as a mirror to push to or fetch from",
+ PARSE_OPT_OPTARG, parse_mirror_opt },
OPT_END()
};
if (argc < 2)
usage_with_options(builtin_remote_add_usage, options);
+ if (mirror && master)
+ die("specifying a master branch makes no sense with --mirror");
+ if (mirror && track.nr)
+ die("specifying branches to track makes no sense with --mirror");
+
name = argv[0];
url = argv[1];
if (git_config_set(buf.buf, url))
return 1;
- strbuf_reset(&buf);
- strbuf_addf(&buf, "remote.%s.fetch", name);
-
- if (track.nr == 0)
- string_list_append(&track, "*");
- for (i = 0; i < track.nr; i++) {
- if (add_branch(buf.buf, track.items[i].string,
- name, mirror, &buf2))
- return 1;
+ if (!mirror || mirror & MIRROR_FETCH) {
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "remote.%s.fetch", name);
+ if (track.nr == 0)
+ string_list_append(&track, "*");
+ for (i = 0; i < track.nr; i++) {
+ if (add_branch(buf.buf, track.items[i].string,
+ name, mirror, &buf2))
+ return 1;
+ }
}
- if (mirror) {
+ if (mirror & MIRROR_PUSH) {
strbuf_reset(&buf);
strbuf_addf(&buf, "remote.%s.mirror", name);
if (git_config_set(buf.buf, "true"))
struct option options[] = {
OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"),
- OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
+ { OPTION_BOOLEAN, 'r', NULL, &noop, NULL, "no-op (backward compatibility)",
+ PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 0 },
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
extern size_t packed_git_window_size;
extern size_t packed_git_limit;
extern size_t delta_base_cache_limit;
+extern unsigned long big_file_threshold;
extern int read_replace_refs;
extern int fsync_object_files;
extern int core_preload_index;
/*
* Note, this isn't a complete replacement for getaddrinfo. It assumes
- * that service contains a numerical port, or that it it is null. It
+ * that service contains a numerical port, or that it is null. It
* does a simple search using gethostbyname, and returns one IPv4 host
* if one was found.
*/
If you don't like either of these options, you can define
CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
- else. And if if you are sure that your program using malloc has
+ else. And if you are sure that your program using malloc has
no errors or vulnerabilities, you can define INSECURE to 1,
which might (or might not) provide a small performance improvement.
of the same size are arranged in a circularly-linked list, with only
the oldest chunk (the next to be used, in our FIFO ordering)
actually in the tree. (Tree members are distinguished by a non-null
- parent pointer.) If a chunk with the same size an an existing node
+ parent pointer.) If a chunk with the same size as an existing node
is inserted, it is linked off the existing node using pointers that
work in the same way as fd/bk pointers of small chunks.
Each tree contains a power of 2 sized range of chunk sizes (the
- smallest is 0x100 <= x < 0x180), which is is divided in half at each
+ smallest is 0x100 <= x < 0x180), which is divided in half at each
tree level, with the chunks in the smaller half of the range (0x100
<= x < 0x140 for the top nose) in the left subtree and the larger
half (0x140 <= x < 0x180) in the right subtree. This is, of course,
least-preferred order):
1. A call to MORECORE that can normally contiguously extend memory.
(disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
- or main space is mmapped or a previous contiguous call failed)
+ main space is mmapped or a previous contiguous call failed)
2. A call to MMAP new space (disabled if not HAVE_MMAP).
Note that under the default settings, if MORECORE is unable to
fulfill a request, and HAVE_MMAP is true, then mmap is
structure of old version, but most details differ.)
*/
-
-
return 0;
}
+ if (!strcmp(var, "core.bigfilethreshold")) {
+ long n = git_config_int(var, value);
+ big_file_threshold = 0 < n ? n : 0;
+ return 0;
+ }
+
if (!strcmp(var, "core.packedgitlimit")) {
packed_git_limit = git_config_int(var, value);
return 0;
#!bash
#
-# bash completion support for core Git.
+# bash/zsh completion support for core Git.
#
# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
# To use these routines:
#
# 1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
-# 2) Added the following line to your .bashrc:
-# source ~/.git-completion.sh
-#
-# Or, add the following lines to your .zshrc:
-# autoload bashcompinit
-# bashcompinit
+# 2) Add the following line to your .bashrc/.zshrc:
# source ~/.git-completion.sh
#
# 3) Consider changing your PS1 to also show the current branch:
-# PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
+# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
+# ZSH: PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
#
# The argument to __git_ps1 will be displayed only if you
# are currently in a git repository. The %s token will be
# git@vger.kernel.org
#
+if [[ -n ${ZSH_VERSION-} ]]; then
+ autoload -U +X bashcompinit && bashcompinit
+fi
+
case "$COMP_WORDBREAKS" in
*:*) : great ;;
*) COMP_WORDBREAKS="$COMP_WORDBREAKS:"
try:
while True:
entry = marshal.load(p4.stdout)
- if cb is not None:
- cb(entry)
- else:
- result.append(entry)
+ if cb is not None:
+ cb(entry)
+ else:
+ result.append(entry)
except EOFError:
pass
exitCode = p4.wait()
changes = {}
for line in output:
- changeNum = int(line.split(" ")[1])
- changes[changeNum] = True
+ changeNum = int(line.split(" ")[1])
+ changes[changeNum] = True
changelist = changes.keys()
changelist.sort()
# - helper for streamP4Files
def streamOneP4File(self, file, contents):
- if file["type"] == "apple":
- print "\nfile %s is a strange apple file that forks. Ignoring" % \
- file['depotFile']
- return
+ if file["type"] == "apple":
+ print "\nfile %s is a strange apple file that forks. Ignoring" % \
+ file['depotFile']
+ return
relPath = self.stripRepoPath(file['depotFile'], self.branchPrefixes)
relPath = self.wildcard_decode(relPath)
# handle another chunk of streaming data
def streamP4FilesCb(self, marshalled):
- if marshalled.has_key('depotFile') and self.stream_have_file_info:
- # start of a new file - output the old one first
- self.streamOneP4File(self.stream_file, self.stream_contents)
- self.stream_file = {}
- self.stream_contents = []
- self.stream_have_file_info = False
+ if marshalled.has_key('depotFile') and self.stream_have_file_info:
+ # start of a new file - output the old one first
+ self.streamOneP4File(self.stream_file, self.stream_contents)
+ self.stream_file = {}
+ self.stream_contents = []
+ self.stream_have_file_info = False
- # pick up the new file information... for the
- # 'data' field we need to append to our array
- for k in marshalled.keys():
- if k == 'data':
- self.stream_contents.append(marshalled['data'])
- else:
- self.stream_file[k] = marshalled[k]
+ # pick up the new file information... for the
+ # 'data' field we need to append to our array
+ for k in marshalled.keys():
+ if k == 'data':
+ self.stream_contents.append(marshalled['data'])
+ else:
+ self.stream_file[k] = marshalled[k]
- self.stream_have_file_info = True
+ self.stream_have_file_info = True
# Stream directly from "p4 files" into "git fast-import"
def streamP4Files(self, files):
self.stream_contents = []
self.stream_have_file_info = False
- # curry self argument
- def streamP4FilesCbSelf(entry):
- self.streamP4FilesCb(entry)
+ # curry self argument
+ def streamP4FilesCbSelf(entry):
+ self.streamP4FilesCb(entry)
- p4CmdList("-x - print",
- '\n'.join(['%s#%s' % (f['path'], f['rev'])
+ p4CmdList("-x - print",
+ '\n'.join(['%s#%s' % (f['path'], f['rev'])
for f in filesToRead]),
- cb=streamP4FilesCbSelf)
+ cb=streamP4FilesCbSelf)
# do the last chunk
if self.stream_file.has_key('depotFile'):
def commit(self, details, files, branch, branchPrefixes, parent = ""):
epoch = details["time"]
author = details["user"]
- self.branchPrefixes = branchPrefixes
+ self.branchPrefixes = branchPrefixes
if self.verbose:
print "commit into %s" % branch
s = ''
for (key, val) in self.users.items():
- s += "%s\t%s\n" % (key.expandtabs(1), val.expandtabs(1))
+ s += "%s\t%s\n" % (key.expandtabs(1), val.expandtabs(1))
open(self.getUserCacheFilename(), "wb").write(s)
self.userMapFromPerforceServer = True
dir = opendir(path->buf);
if (!dir)
- return -1;
+ return rmdir(path->buf);
if (path->buf[original_len - 1] != '/')
strbuf_addch(path, '/');
size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
size_t delta_base_cache_limit = 16 * 1024 * 1024;
+unsigned long big_file_threshold = 512 * 1024 * 1024;
const char *pager_program;
int pager_use_color = 1;
const char *editor_program;
/* Configured limits on output */
static unsigned long max_depth = 10;
static off_t max_packsize;
-static uintmax_t big_file_threshold = 512 * 1024 * 1024;
static int force_update;
static int pack_compression_level = Z_DEFAULT_COMPRESSION;
static int pack_compression_seen;
max_packsize = git_config_ulong(k, v);
return 0;
}
- if (!strcmp(k, "core.bigfilethreshold")) {
- long n = git_config_int(k, v);
- big_file_threshold = 0 < n ? n : 0;
- }
return git_default_config(k, v, cb);
}
}
/* Mark msgid for translation but do not translate it. */
-#define N_(msgid) (msgid)
+#define N_(msgid) msgid
#endif
#endif
#ifndef __MINGW32__
#include <sys/wait.h>
+#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <termios.h>
--recurse-submodules)
recurse_submodules=--recurse-submodules
;;
+ --recurse-submodules=*)
+ recurse_submodules="$1"
+ ;;
--no-recurse-submodules)
recurse_submodules=--no-recurse-submodules
;;
assert_stash_like "$@"
- git update-index -q --refresh &&
- git diff-files --quiet --ignore-submodules ||
- die 'Cannot apply to a dirty working tree, please stage your changes'
+ git update-index -q --refresh || die 'unable to refresh index'
# current index state
c_tree=$(git write-tree) ||
#
module_list()
{
- git ls-files --error-unmatch --stage -- "$@" | sane_grep '^160000 '
+ git ls-files --error-unmatch --stage -- "$@" |
+ perl -e '
+ my %unmerged = ();
+ my ($null_sha1) = ("0" x 40);
+ while (<STDIN>) {
+ chomp;
+ my ($mode, $sha1, $stage, $path) =
+ /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
+ next unless $mode eq "160000";
+ if ($stage ne "0") {
+ if (!$unmerged{$path}++) {
+ print "$mode $null_sha1 U\t$path\n";
+ }
+ next;
+ }
+ print "$_\n";
+ }
+ '
}
#
module_list "$@" |
while read mode sha1 stage path
do
+ if test "$stage" = U
+ then
+ echo >&2 "Skipping unmerged submodule $path"
+ continue
+ fi
name=$(module_name "$path") || exit
url=$(git config submodule."$name".url)
update_module=$(git config submodule."$name".update)
if test -z "$nofetch"
then
+ # Run fetch only if $sha1 isn't present or it
+ # is not reachable from a ref.
(clear_local_git_env; cd "$path" &&
- git-fetch) ||
+ ((rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
+ test -z "$rev") || git-fetch)) ||
die "Unable to fetch in submodule path '$path'"
fi
name=$(module_name "$path") || exit
url=$(git config submodule."$name".url)
displaypath="$prefix$path"
+ if test "$stage" = U
+ then
+ say "U$sha1 $displaypath"
+ continue
+ fi
if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
then
say "-$sha1 $displaypath"
use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
use IPC::Open3;
use Git;
+use Memoize; # core since 5.8.0, Jul 2002
BEGIN {
# import functions from Git into our packages, en masse
*{"${package}::$_"} = \&{"Git::$_"};
}
}
+ Memoize::memoize 'Git::config';
+ Memoize::memoize 'Git::config_bool';
}
my ($SVN);
$url = eval { command_oneline('config', '--get',
"svn-remote.$gs->{repo_id}.commiturl") };
if (!$url) {
- $url = $gs->full_url
+ $url = $gs->full_pushurl
}
}
$head ||= 'HEAD';
my (undef, $rev, undef, $gs) = working_head_info($head);
- my $src = $gs->full_url;
+ my $src = $gs->full_pushurl;
my $remote = Git::SVN::read_all_remotes()->{$gs->{repo_id}};
my $allglobs = $remote->{ $_tag ? 'tags' : 'branches' };
$url = eval { command_oneline('config', '--get',
"svn-remote.$gs->{repo_id}.commiturl") };
if (!$url) {
- $url = $remote->{url};
+ $url = $remote->{pushurl} || $remote->{url};
}
}
my $dst = join '/', $url, $lft, $branch_name, ($rgt || ());
print "$result\n" if $result;
}
+sub auto_create_empty_directories {
+ my ($gs) = @_;
+ my $var = eval { command_oneline('config', '--get', '--bool',
+ "svn-remote.$gs->{repo_id}.automkdirs") };
+ # By default, create empty directories by consulting the unhandled log,
+ # but allow setting it to 'false' to skip it.
+ return !($var && $var eq 'false');
+}
+
sub cmd_rebase {
command_noisy(qw/update-index --refresh/);
my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
$_fetch_all ? $gs->fetch_all : $gs->fetch;
}
command_noisy(rebase_cmd(), $gs->refname);
- $gs->mkemptydirs;
+ if (auto_create_empty_directories($gs)) {
+ $gs->mkemptydirs;
+ }
}
sub cmd_show_ignore {
command_noisy(qw/read-tree -m -u -v HEAD HEAD/);
print STDERR "Checked out HEAD:\n ",
$gs->full_url, " r", $gs->last_rev, "\n";
- $gs->mkemptydirs($gs->last_rev);
+ if (auto_create_empty_directories($gs)) {
+ $gs->mkemptydirs($gs->last_rev);
+ }
}
sub complete_svn_url {
$r->{$1}->{svm} = {};
} elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
$r->{$1}->{url} = $2;
+ } elsif (m!^(.+)\.pushurl=\s*(.*)\s*$!) {
+ $r->{$1}->{pushurl} = $2;
} elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) {
my ($remote, $t, $local_ref, $remote_ref) =
($1, $2, $3, $4);
$self->{url} = command_oneline('config', '--get',
"svn-remote.$repo_id.url") or
die "Failed to read \"svn-remote.$repo_id.url\" in config\n";
+ $self->{pushurl} = eval { command_oneline('config', '--get',
+ "svn-remote.$repo_id.pushurl") };
$self->rebuild;
$self;
}
$self->{url} . (length $self->{path} ? '/' . $self->{path} : '');
}
+sub full_pushurl {
+ my ($self) = @_;
+ if ($self->{pushurl}) {
+ return $self->{pushurl} . (length $self->{path} ? '/' .
+ $self->{path} : '');
+ } else {
+ return $self->full_url;
+ }
+}
sub set_commit_header_env {
my ($log_entry) = @_;
Memoize::unmemoize 'check_cherry_pick';
Memoize::unmemoize 'has_no_changes';
}
+
+ Memoize::memoize 'Git::SVN::repos_root';
}
END {
global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
global cmitmode wrapcomment datetimeformat limitdiffs
global colors uicolor bgcolor fgcolor diffcolors diffcontext selectbgcolor
- global autoselect extdifftool perfile_attrs markbgcolor use_ttk
+ global autoselect autosellen extdifftool perfile_attrs markbgcolor use_ttk
global hideremotes want_ttk
if {$stuffsaved} return
puts $f [list set cmitmode $cmitmode]
puts $f [list set wrapcomment $wrapcomment]
puts $f [list set autoselect $autoselect]
+ puts $f [list set autosellen $autosellen]
puts $f [list set showneartags $showneartags]
puts $f [list set hideremotes $hideremotes]
puts $f [list set showlocalchanges $showlocalchanges]
-width $lthickness -fill black -tags tag.$id]
$canv lower $t
foreach tag $marks x $xvals wid $wvals {
+ set tag_quoted [string map {% %%} $tag]
set xl [expr {$x + $delta}]
set xr [expr {$x + $delta + $wid + $lthickness}]
set font mainfont
set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
$xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
-width 1 -outline black -fill yellow -tags tag.$id]
- $canv bind $t <1> [list showtag $tag 1]
+ $canv bind $t <1> [list showtag $tag_quoted 1]
set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
} else {
# draw a head or other ref
set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
-font $font -tags [list tag.$id text]]
if {$ntags >= 0} {
- $canv bind $t <1> [list showtag $tag 1]
+ $canv bind $t <1> [list showtag $tag_quoted 1]
} elseif {$nheads >= 0} {
- $canv bind $t $ctxbut [list headmenu %X %Y $id $tag]
+ $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]
}
}
return $xt
global mergemax numcommits pending_select
global cmitmode showneartags allcommits
global targetrow targetid lastscrollrows
- global autoselect jump_to_here
+ global autoselect autosellen jump_to_here
catch {unset pending_select}
$canv delete hover
$sha1entry delete 0 end
$sha1entry insert 0 $id
if {$autoselect} {
- $sha1entry selection range 0 end
+ $sha1entry selection range 0 $autosellen
}
rhighlight_sel $id
to file '%s'.\nPlease commit, reset or stash\
your changes and try again." $fname]
} elseif {[regexp -line \
- {^(CONFLICT \(.*\):|Automatic cherry-pick failed)} \
+ {^(CONFLICT \(.*\):|Automatic cherry-pick failed|error: could not apply)} \
$err]} {
if {[confirm_popup [mc "Cherry-pick failed because of merge\
conflict.\nDo you wish to run git citool to\
global maxwidth maxgraphpct use_ttk NS
global oldprefs prefstop showneartags showlocalchanges
global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
- global tabstop limitdiffs autoselect extdifftool perfile_attrs
+ global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
global hideremotes want_ttk have_ttk
set top .gitkprefs
${NS}::checkbutton $top.showlocal -text [mc "Show local changes"] \
-variable showlocalchanges
grid x $top.showlocal -sticky w
- ${NS}::checkbutton $top.autoselect -text [mc "Auto-select SHA1"] \
+ ${NS}::checkbutton $top.autoselect -text [mc "Auto-select SHA1 (length)"] \
-variable autoselect
- grid x $top.autoselect -sticky w
+ spinbox $top.autosellen -from 1 -to 40 -width 4 -textvariable autosellen
+ grid x $top.autoselect $top.autosellen -sticky w
${NS}::checkbutton $top.hideremotes -text [mc "Hide remote refs"] \
-variable hideremotes
grid x $top.hideremotes -sticky w
set limitdiffs 1
set datetimeformat "%Y-%m-%d %H:%M:%S"
set autoselect 1
+set autosellen 40
set perfile_attrs 0
set want_ttk 1
set use_ttk [expr {$have_ttk && $want_ttk}]
set NS [expr {$use_ttk ? "ttk" : ""}]
-set git_version [join [lrange [split [lindex [exec git version] end] .] 0 2] .]
+regexp {^git version ([\d.]*\d)} [exec git version] _ git_version
set show_notes {}
if {[package vcompare $git_version "1.6.6.2"] >= 0} {
#: gitk:323
msgid "Error executing --argscmd command:"
-msgstr "Ошибка выполнения команды заданой --argscmd:"
+msgstr "Ð\9eÑ\88ибка вÑ\8bполнениÑ\8f командÑ\8b заданной --argscmd:"
#: gitk:336
msgid "No files selected: --merge specified but no files are unmerged."
"No files selected: --merge specified but no unmerged files are within file "
"limit."
msgstr ""
-"Файлы не выбраны: указан --merge, но в рамках указаного "
+"ФайлÑ\8b не вÑ\8bбÑ\80анÑ\8b: Ñ\83казан --merge, но в Ñ\80амкаÑ\85 Ñ\83казанного "
"ограничения на имена файлов нет ни одного "
"где эта операция должна быть завершена."
#: gitk:2326 gitk:2339
msgid "Diff this -> selected"
-msgstr "Сравнить это состояние с выделеным"
+msgstr "Сравнить это состояние с выделенным"
#: gitk:2327 gitk:2340
msgid "Diff selected -> this"
-msgstr "Сравнить выделеное с этим состоянием"
+msgstr "СÑ\80авниÑ\82Ñ\8c вÑ\8bделенное Ñ\81 Ñ\8dÑ\82им Ñ\81оÑ\81Ñ\82оÑ\8fнием"
#: gitk:2328 gitk:2341
msgid "Make patch"
#: gitk:2666
#, tcl-format
msgid "<%s-G>\t\tMove to next find hit"
-msgstr "<%s-G>\t\tПерейти к следующему найденому состоянию"
+msgstr "<%s-G>\t\tÐ\9fеÑ\80ейÑ\82и к Ñ\81ледÑ\83Ñ\8eÑ\89емÑ\83 найденномÑ\83 Ñ\81оÑ\81Ñ\82оÑ\8fниÑ\8e"
#: gitk:2667
msgid "<Return>\tMove to next find hit"
-msgstr "<Return>\tПерейти к следующему найденому состоянию"
+msgstr "<Return>\tÐ\9fеÑ\80ейÑ\82и к Ñ\81ледÑ\83Ñ\8eÑ\89емÑ\83 найденномÑ\83 Ñ\81оÑ\81Ñ\82оÑ\8fниÑ\8e"
#: gitk:2668
msgid "/\t\tFocus the search box"
#: gitk:2669
msgid "?\t\tMove to previous find hit"
-msgstr "?\t\tПерейти к предыдущему найденому состоянию"
+msgstr "?\t\tÐ\9fеÑ\80ейÑ\82и к пÑ\80едÑ\8bдÑ\83Ñ\89емÑ\83 найденномÑ\83 Ñ\81оÑ\81Ñ\82оÑ\8fниÑ\8e"
#: gitk:2670
msgid "f\t\tScroll diff view to next file"
#: gitk:2672
#, tcl-format
msgid "<%s-R>\t\tSearch for previous hit in diff view"
-msgstr "<%s-R>\t\tПерейти к предыдущему найденому тексту в списке изменений"
+msgstr "<%s-R>\t\tÐ\9fеÑ\80ейÑ\82и к пÑ\80едÑ\8bдÑ\83Ñ\89емÑ\83 найденномÑ\83 Ñ\82екÑ\81Ñ\82Ñ\83 в Ñ\81пиÑ\81ке изменений"
#: gitk:2673
#, tcl-format
#: gitk:8472
msgid "Mixed: Leave working tree untouched, reset index"
msgstr ""
-"Смешаный: оставить рабочий каталог неизменным, установить индекс"
+"Смешанный: оставить рабочий каталог неизменным, установить индекс"
#: gitk:8475
msgid ""
#: gitk:10126
msgid "Limit diffs to listed paths"
-msgstr "Ограничить показ изменений выбраными файлами"
+msgstr "Ограничить показ изменений выбранными файлами"
#: gitk:10129
msgid "Support per-file encodings"
#: gitk:10169
msgid "Marked line bg"
-msgstr "Фон выбраной строки"
+msgstr "Фон вÑ\8bбÑ\80анной Ñ\81Ñ\82Ñ\80оки"
#: gitk:10171
msgid "marked line background"
-msgstr "фон выбраной строки"
+msgstr "Ñ\84он вÑ\8bбÑ\80анной Ñ\81Ñ\82Ñ\80оки"
#: gitk:10175
msgid "Select bg"
The filesystem traversing limit for getting the project list; the number
is taken as depth relative to the projectroot. It is used when
GITWEB_LIST is a directory (or is not set; then project root is used).
- Is is meant to speed up project listing on large work trees by limiting
+ This is meant to speed up project listing on large work trees by limiting
search depth. [Default: 2007]
* GITWEB_LIST
Points to a directory to scan for projects (defaults to project root
* used to extract hours and minutes from timezone info, e.g '-0900'
* @constant
*/
-var tzRe = /^([+-][0-9][0-9])([0-9][0-9])$/;
+var tzRe = /^([+-])([0-9][0-9])([0-9][0-9])$/;
+
+/**
+ * convert numeric timezone +/-ZZZZ to offset from UTC in seconds
+ *
+ * @param {String} timezoneInfo: numeric timezone '(+|-)HHMM'
+ * @returns {Number} offset from UTC in seconds for timezone
+ *
+ * @globals tzRe
+ */
+function timezoneOffset(timezoneInfo) {
+ var match = tzRe.exec(timezoneInfo);
+ var tz_sign = (match[1] === '-' ? -1 : +1);
+ var tz_hour = parseInt(match[2],10);
+ var tz_min = parseInt(match[3],10);
+
+ return tz_sign*(((tz_hour*60) + tz_min)*60);
+}
/**
* return date in local time formatted in iso-8601 like format
* @param {Number} epoch: seconds since '00:00:00 1970-01-01 UTC'
* @param {String} timezoneInfo: numeric timezone '(+|-)HHMM'
* @returns {String} date in local time in iso-8601 like format
- *
- * @globals tzRe
*/
function formatDateISOLocal(epoch, timezoneInfo) {
- var match = tzRe.exec(timezoneInfo);
// date corrected by timezone
var localDate = new Date(1000 * (epoch +
- (parseInt(match[1],10)*3600 + parseInt(match[2],10)*60)));
+ timezoneOffset(timezoneInfo)));
var localDateStr = // e.g. '2005-08-07'
localDate.getUTCFullYear() + '-' +
padLeft(localDate.getUTCMonth()+1, 2, '0') + '-' +
static void notify_parent(void)
{
- /*
- * execvp failed. If possible, we'd like to let start_command
- * know, so failures like ENOENT can be handled right away; but
- * otherwise, finish_command will still report the error.
- */
- if (write(child_notifier, "", 1))
- ; /* yes, dear gcc -D_FORTIFY_SOURCE, there was an error. */
+ ssize_t unused;
+ unused = write(child_notifier, "", 1);
}
static NORETURN void die_child(const char *err, va_list params)
{
char msg[4096];
+ ssize_t unused;
int len = vsnprintf(msg, sizeof(msg), err, params);
if (len > sizeof(msg))
len = sizeof(msg);
- if (write(child_err, "fatal: ", 7) ||
- write(child_err, msg, len) ||
- write(child_err, "\n", 1))
- ; /* yes, gcc -D_FORTIFY_SOURCE, we know there was an error. */
+ unused = write(child_err, "fatal: ", 7);
+ unused = write(child_err, msg, len);
+ unused = write(child_err, "\n", 1);
exit(128);
}
#endif
enum object_type type;
/* use_pack() assures us we have [base, base + 20) available
- * as a range that we can look at at. (Its actually the hash
+ * as a range that we can look at. (Its actually the hash
* size that is assured.) With our object header encoding
* the maximum deflated object size is 2^137, which is just
* insane, so we know won't exceed what we have been given.
if (!get_tree_entry(tree_sha1, fullname,
sha1, &mode)) {
die("Path '%s' exists, but not '%s'.\n"
- "Did you mean '%s:%s'?",
+ "Did you mean '%s:%s' aka '%s:./%s'?",
fullname,
filename,
object_name,
- fullname);
+ fullname,
+ object_name,
+ filename);
}
die("Path '%s' does not exist in '%s'",
filename, object_name);
if (ce_namelen(ce) == fullnamelen &&
!memcmp(ce->name, fullname, fullnamelen))
die("Path '%s' is in the index, but not '%s'.\n"
- "Did you mean ':%d:%s'?",
+ "Did you mean ':%d:%s' aka ':%d:./%s'?",
fullname, filename,
- ce_stage(ce), fullname);
+ ce_stage(ce), fullname,
+ ce_stage(ce), filename);
}
if (!lstat(filename, &st))
static struct string_list config_name_for_path;
static struct string_list config_fetch_recurse_submodules_for_name;
static struct string_list config_ignore_for_name;
-static int config_fetch_recurse_submodules;
+static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
+static struct string_list changed_submodule_paths;
static int add_submodule_odb(const char *path)
{
if (!prefixcmp(var, "submodule."))
return parse_submodule_config_option(var, value);
else if (!strcmp(var, "fetch.recursesubmodules")) {
- config_fetch_recurse_submodules = git_config_bool(var, value);
+ config_fetch_recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
return 0;
}
return 0;
if (!config)
config = string_list_append(&config_fetch_recurse_submodules_for_name,
strbuf_detach(&submodname, NULL));
- config->util = git_config_bool(var, value) ? (void *)1 : NULL;
+ config->util = (void *)(intptr_t)parse_fetch_recurse_submodules_arg(var, value);
strbuf_release(&submodname);
} else if ((len > 7) && !strcmp(var + len - 7, ".ignore")) {
if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
strbuf_release(&sb);
}
+int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
+{
+ switch (git_config_maybe_bool(opt, arg)) {
+ case 1:
+ return RECURSE_SUBMODULES_ON;
+ case 0:
+ return RECURSE_SUBMODULES_OFF;
+ default:
+ if (!strcmp(arg, "on-demand"))
+ return RECURSE_SUBMODULES_ON_DEMAND;
+ die("bad %s argument: %s", opt, arg);
+ }
+}
+
void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
unsigned dirty_submodule,
config_fetch_recurse_submodules = value;
}
+static int is_submodule_commit_present(const char *path, unsigned char sha1[20])
+{
+ int is_present = 0;
+ if (!add_submodule_odb(path) && lookup_commit_reference(sha1)) {
+ /* Even if the submodule is checked out and the commit is
+ * present, make sure it is reachable from a ref. */
+ struct child_process cp;
+ const char *argv[] = {"rev-list", "-n", "1", NULL, "--not", "--all", NULL};
+ struct strbuf buf = STRBUF_INIT;
+
+ argv[3] = sha1_to_hex(sha1);
+ memset(&cp, 0, sizeof(cp));
+ cp.argv = argv;
+ cp.env = local_repo_env;
+ cp.git_cmd = 1;
+ cp.no_stdin = 1;
+ cp.out = -1;
+ cp.dir = path;
+ if (!run_command(&cp) && !strbuf_read(&buf, cp.out, 1024))
+ is_present = 1;
+
+ close(cp.out);
+ strbuf_release(&buf);
+ }
+ return is_present;
+}
+
+static void submodule_collect_changed_cb(struct diff_queue_struct *q,
+ struct diff_options *options,
+ void *data)
+{
+ int i;
+ for (i = 0; i < q->nr; i++) {
+ struct diff_filepair *p = q->queue[i];
+ if (!S_ISGITLINK(p->two->mode))
+ continue;
+
+ if (S_ISGITLINK(p->one->mode)) {
+ /* NEEDSWORK: We should honor the name configured in
+ * the .gitmodules file of the commit we are examining
+ * here to be able to correctly follow submodules
+ * being moved around. */
+ struct string_list_item *path;
+ path = unsorted_string_list_lookup(&changed_submodule_paths, p->two->path);
+ if (!path && !is_submodule_commit_present(p->two->path, p->two->sha1))
+ string_list_append(&changed_submodule_paths, xstrdup(p->two->path));
+ } else {
+ /* Submodule is new or was moved here */
+ /* NEEDSWORK: When the .git directories of submodules
+ * live inside the superprojects .git directory some
+ * day we should fetch new submodules directly into
+ * that location too when config or options request
+ * that so they can be checked out from there. */
+ continue;
+ }
+ }
+}
+
+void check_for_new_submodule_commits(unsigned char new_sha1[20])
+{
+ struct rev_info rev;
+ struct commit *commit;
+ const char *argv[] = {NULL, NULL, "--not", "--all", NULL};
+ int argc = ARRAY_SIZE(argv) - 1;
+
+ init_revisions(&rev, NULL);
+ argv[1] = xstrdup(sha1_to_hex(new_sha1));
+ setup_revisions(argc, argv, &rev, NULL);
+ if (prepare_revision_walk(&rev))
+ die("revision walk setup failed");
+
+ /*
+ * Collect all submodules (whether checked out or not) for which new
+ * commits have been recorded upstream in "changed_submodule_paths".
+ */
+ while ((commit = get_revision(&rev))) {
+ struct commit_list *parent = commit->parents;
+ while (parent) {
+ struct diff_options diff_opts;
+ diff_setup(&diff_opts);
+ diff_opts.output_format |= DIFF_FORMAT_CALLBACK;
+ diff_opts.format_callback = submodule_collect_changed_cb;
+ if (diff_setup_done(&diff_opts) < 0)
+ die("diff_setup_done failed");
+ diff_tree_sha1(parent->item->object.sha1, commit->object.sha1, "", &diff_opts);
+ diffcore_std(&diff_opts);
+ diff_flush(&diff_opts);
+ parent = parent->next;
+ }
+ }
+ free((char *)argv[1]);
+}
+
int fetch_populated_submodules(int num_options, const char **options,
- const char *prefix, int ignore_config,
+ const char *prefix, int command_line_option,
int quiet)
{
- int i, result = 0, argc = 0;
+ int i, result = 0, argc = 0, default_argc;
struct child_process cp;
const char **argv;
struct string_list_item *name_for_path;
const char *work_tree = get_git_work_tree();
if (!work_tree)
- return 0;
+ goto out;
if (!the_index.initialized)
if (read_cache() < 0)
die("index file corrupt");
- /* 4: "fetch" (options) "--submodule-prefix" prefix NULL */
- argv = xcalloc(num_options + 4, sizeof(const char *));
+ /* 6: "fetch" (options) --recurse-submodules-default default "--submodule-prefix" prefix NULL */
+ argv = xcalloc(num_options + 6, sizeof(const char *));
argv[argc++] = "fetch";
for (i = 0; i < num_options; i++)
argv[argc++] = options[i];
+ argv[argc++] = "--recurse-submodules-default";
+ default_argc = argc++;
argv[argc++] = "--submodule-prefix";
memset(&cp, 0, sizeof(cp));
struct strbuf submodule_git_dir = STRBUF_INIT;
struct strbuf submodule_prefix = STRBUF_INIT;
struct cache_entry *ce = active_cache[i];
- const char *git_dir, *name;
+ const char *git_dir, *name, *default_argv;
if (!S_ISGITLINK(ce->ce_mode))
continue;
if (name_for_path)
name = name_for_path->util;
- if (!ignore_config) {
+ default_argv = "yes";
+ if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
struct string_list_item *fetch_recurse_submodules_option;
fetch_recurse_submodules_option = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name);
if (fetch_recurse_submodules_option) {
- if (!fetch_recurse_submodules_option->util)
+ if ((intptr_t)fetch_recurse_submodules_option->util == RECURSE_SUBMODULES_OFF)
continue;
+ if ((intptr_t)fetch_recurse_submodules_option->util == RECURSE_SUBMODULES_ON_DEMAND) {
+ if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
+ continue;
+ default_argv = "on-demand";
+ }
} else {
- if (!config_fetch_recurse_submodules)
+ if (config_fetch_recurse_submodules == RECURSE_SUBMODULES_OFF)
continue;
+ if (config_fetch_recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) {
+ if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
+ continue;
+ default_argv = "on-demand";
+ }
}
+ } else if (command_line_option == RECURSE_SUBMODULES_ON_DEMAND) {
+ if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
+ continue;
+ default_argv = "on-demand";
}
strbuf_addf(&submodule_path, "%s/%s", work_tree, ce->name);
if (!quiet)
printf("Fetching submodule %s%s\n", prefix, ce->name);
cp.dir = submodule_path.buf;
+ argv[default_argc] = default_argv;
argv[argc] = submodule_prefix.buf;
if (run_command(&cp))
result = 1;
strbuf_release(&submodule_prefix);
}
free(argv);
+out:
+ string_list_clear(&changed_submodule_paths, 1);
return result;
}
struct diff_options;
+enum {
+ RECURSE_SUBMODULES_ON_DEMAND = -1,
+ RECURSE_SUBMODULES_OFF = 0,
+ RECURSE_SUBMODULES_DEFAULT = 1,
+ RECURSE_SUBMODULES_ON = 2
+};
+
void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
const char *path);
int submodule_config(const char *var, const char *value, void *cb);
void gitmodules_config();
int parse_submodule_config_option(const char *var, const char *value);
void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
+int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
unsigned dirty_submodule,
const char *del, const char *add, const char *reset);
void set_config_fetch_recurse_submodules(int value);
+void check_for_new_submodule_commits(unsigned char new_sha1[20]);
int fetch_populated_submodules(int num_options, const char **options,
- const char *prefix, int ignore_config,
+ const char *prefix, int command_line_option,
int quiet);
unsigned is_submodule_modified(const char *path, int ignore_untracked);
int merge_submodule(unsigned char result[20], const char *path, const unsigned char base[20],
test -d realgitdir/refs
'
-test_expect_success 're-init to move gitdir symlink' '
+test_expect_success SYMLINKS 're-init to move gitdir symlink' '
rm -rf newdir realgitdir &&
git init newdir &&
(
test_cmp expect actual
'
+test_expect_success 'reflog default format' '
+ git reflog -1 >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+commit e46513e
+Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
+Reflog message: commit (initial): one
+Author: A U Thor <author@example.com>
+
+ one
+EOF
+test_expect_success 'override reflog default format' '
+ git reflog --format=short -1 >actual &&
+ test_cmp expect actual
+'
+
cat >expect <<'EOF'
Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter <committer@example.com>)
Reflog message: commit (initial): one
. ./test-lib.sh
+test_did_you_mean ()
+{
+ printf "fatal: Path '$2$3' $4, but not ${5:-'$3'}.\n" >expected &&
+ printf "Did you mean '$1:$2$3'${2:+ aka '$1:./$3'}?\n" >>expected &&
+ test_cmp expected error
+}
+
HASH_file=
test_expect_success 'set up basic repo' '
grep "fatal: Path '"'"'index-only.txt'"'"' exists on disk, but not in '"'"'HEAD'"'"'." error &&
(cd subdir &&
test_must_fail git rev-parse HEAD:file2.txt 2> error &&
- grep "Did you mean '"'"'HEAD:subdir/file2.txt'"'"'?" error )
+ test_did_you_mean HEAD subdir/ file2.txt exists )
'
test_expect_success 'incorrect file in :path and :N:path' '
test_must_fail git rev-parse :1:nothing.txt 2> error &&
grep "Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error &&
test_must_fail git rev-parse :1:file.txt 2> error &&
- grep "Did you mean '"'"':0:file.txt'"'"'?" error &&
+ test_did_you_mean ":0" "" file.txt "is in the index" "at stage 1" &&
(cd subdir &&
test_must_fail git rev-parse :1:file.txt 2> error &&
- grep "Did you mean '"'"':0:file.txt'"'"'?" error &&
+ test_did_you_mean ":0" "" file.txt "is in the index" "at stage 1" &&
test_must_fail git rev-parse :file2.txt 2> error &&
- grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error &&
+ test_did_you_mean ":0" subdir/ file2.txt "is in the index" &&
test_must_fail git rev-parse :2:file2.txt 2> error &&
- grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error) &&
+ test_did_you_mean :0 subdir/ file2.txt "is in the index") &&
test_must_fail git rev-parse :disk-only.txt 2> error &&
grep "fatal: Path '"'"'disk-only.txt'"'"' exists on disk, but not in the index." error
'
git commit -m "dir to symlink"
'
-test_expect_failure SYMLINKS 'checkout commit with dir must not remove untracked a/b' '
+test_expect_success SYMLINKS 'checkout commit with dir must not remove untracked a/b' '
git rm --cached a/b &&
git commit -m "un-track the symlink" &&
git add file3 &&
test_tick &&
git commit -m 3rd &&
+ COMMIT_FILE=.git/objects/5e/e1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
+ test -f $COMMIT_FILE &&
+ test-chmtime =+0 $COMMIT_FILE &&
git notes add -m "Note #3"
'
test_cmp output expect
'
-test_expect_success 'apply needs clean working directory' '
- echo 4 > other-file &&
+test_expect_success 'apply does not need clean working directory' '
+ echo 4 >other-file &&
git add other-file &&
- echo 5 > other-file &&
- test_must_fail git stash apply
+ echo 5 >other-file &&
+ git stash apply &&
+ echo 3 >expect &&
+ test_cmp expect file
+'
+
+test_expect_success 'apply does not clobber working directory changes' '
+ git reset --hard &&
+ echo 4 >file &&
+ test_must_fail git stash apply &&
+ echo 4 >expect &&
+ test_cmp expect file
'
test_expect_success 'apply stashed changes' '
+ git reset --hard &&
+ echo 5 >other-file &&
git add other-file &&
test_tick &&
git commit -m other-file &&
BLOB=$(echo aleph_0 | git hash-object -w --stdin) &&
BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
- test -f $BLOB_FILE
+ test -f $BLOB_FILE &&
+ test-chmtime =+0 $BLOB_FILE
}
test_expect_success setup '
git rev-parse --verify refs/heads/side)
'
+test_expect_success 'add --mirror=fetch' '
+ mkdir mirror-fetch &&
+ git init mirror-fetch/parent &&
+ (cd mirror-fetch/parent &&
+ test_commit one) &&
+ git init --bare mirror-fetch/child &&
+ (cd mirror-fetch/child &&
+ git remote add --mirror=fetch -f parent ../parent)
+'
+
+test_expect_success 'fetch mirrors act as mirrors during fetch' '
+ (cd mirror-fetch/parent &&
+ git branch new &&
+ git branch -m master renamed
+ ) &&
+ (cd mirror-fetch/child &&
+ git fetch parent &&
+ git rev-parse --verify refs/heads/new &&
+ git rev-parse --verify refs/heads/renamed
+ )
+'
+
+test_expect_success 'fetch mirrors can prune' '
+ (cd mirror-fetch/child &&
+ git remote prune parent &&
+ test_must_fail git rev-parse --verify refs/heads/master
+ )
+'
+
+test_expect_success 'fetch mirrors do not act as mirrors during push' '
+ (cd mirror-fetch/parent &&
+ git checkout HEAD^0
+ ) &&
+ (cd mirror-fetch/child &&
+ git branch -m renamed renamed2 &&
+ git push parent
+ ) &&
+ (cd mirror-fetch/parent &&
+ git rev-parse --verify renamed &&
+ test_must_fail git rev-parse --verify refs/heads/renamed2
+ )
+'
+
+test_expect_success 'add --mirror=push' '
+ mkdir mirror-push &&
+ git init --bare mirror-push/public &&
+ git init mirror-push/private &&
+ (cd mirror-push/private &&
+ test_commit one &&
+ git remote add --mirror=push public ../public
+ )
+'
+
+test_expect_success 'push mirrors act as mirrors during push' '
+ (cd mirror-push/private &&
+ git branch new &&
+ git branch -m master renamed &&
+ git push public
+ ) &&
+ (cd mirror-push/private &&
+ git rev-parse --verify refs/heads/new &&
+ git rev-parse --verify refs/heads/renamed &&
+ test_must_fail git rev-parse --verify refs/heads/master
+ )
+'
+
+test_expect_success 'push mirrors do not act as mirrors during fetch' '
+ (cd mirror-push/public &&
+ git branch -m renamed renamed2 &&
+ git symbolic-ref HEAD refs/heads/renamed2
+ ) &&
+ (cd mirror-push/private &&
+ git fetch public &&
+ git rev-parse --verify refs/heads/renamed &&
+ test_must_fail git rev-parse --verify refs/heads/renamed2
+ )
+'
+
test_expect_success 'add alt && prune' '
(mkdir alttst &&
cd alttst &&
! test -s actual.err
'
+test_expect_success "Recursion doesn't happen when no new commits are fetched in the superproject" '
+ (
+ cd downstream &&
+ (
+ cd submodule &&
+ git config --unset fetch.recurseSubmodules
+ ) &&
+ git config --unset fetch.recurseSubmodules
+ git fetch >../actual.out 2>../actual.err
+ ) &&
+ ! test -s actual.out &&
+ ! test -s actual.err
+'
+
+test_expect_success "Recursion stops when no new submodule commits are fetched" '
+ head1=$(git rev-parse --short HEAD) &&
+ git add submodule &&
+ git commit -m "new submodule" &&
+ head2=$(git rev-parse --short HEAD) &&
+ echo "Fetching submodule submodule" > expect.out.sub &&
+ echo "From $pwd/." > expect.err.sub &&
+ echo " $head1..$head2 master -> origin/master" >> expect.err.sub
+ head -2 expect.err >> expect.err.sub &&
+ (
+ cd downstream &&
+ git fetch >../actual.out 2>../actual.err
+ ) &&
+ test_cmp expect.err.sub actual.err &&
+ test_cmp expect.out.sub actual.out
+'
+
+test_expect_success "Recursion doesn't happen when new superproject commits don't change any submodules" '
+ add_upstream_commit &&
+ head1=$(git rev-parse --short HEAD) &&
+ echo a > file &&
+ git add file &&
+ git commit -m "new file" &&
+ head2=$(git rev-parse --short HEAD) &&
+ echo "From $pwd/." > expect.err.file &&
+ echo " $head1..$head2 master -> origin/master" >> expect.err.file &&
+ (
+ cd downstream &&
+ git fetch >../actual.out 2>../actual.err
+ ) &&
+ ! test -s actual.out &&
+ test_cmp expect.err.file actual.err
+'
+
+test_expect_success "Recursion picks up config in submodule" '
+ (
+ cd downstream &&
+ git fetch --recurse-submodules &&
+ (
+ cd submodule &&
+ git config fetch.recurseSubmodules true
+ )
+ ) &&
+ add_upstream_commit &&
+ head1=$(git rev-parse --short HEAD) &&
+ git add submodule &&
+ git commit -m "new submodule" &&
+ head2=$(git rev-parse --short HEAD) &&
+ echo "From $pwd/." > expect.err.sub &&
+ echo " $head1..$head2 master -> origin/master" >> expect.err.sub &&
+ cat expect.err >> expect.err.sub &&
+ (
+ cd downstream &&
+ git fetch >../actual.out 2>../actual.err &&
+ (
+ cd submodule &&
+ git config --unset fetch.recurseSubmodules
+ )
+ ) &&
+ test_cmp expect.err.sub actual.err &&
+ test_cmp expect.out actual.out
+'
+
+test_expect_success "Recursion picks up all submodules when necessary" '
+ add_upstream_commit &&
+ (
+ cd submodule &&
+ (
+ cd deepsubmodule &&
+ git fetch &&
+ git checkout -q FETCH_HEAD
+ ) &&
+ head1=$(git rev-parse --short HEAD^) &&
+ git add deepsubmodule &&
+ git commit -m "new deepsubmodule"
+ head2=$(git rev-parse --short HEAD) &&
+ echo "From $pwd/submodule" > ../expect.err.sub &&
+ echo " $head1..$head2 master -> origin/master" >> ../expect.err.sub
+ ) &&
+ head1=$(git rev-parse --short HEAD) &&
+ git add submodule &&
+ git commit -m "new submodule" &&
+ head2=$(git rev-parse --short HEAD) &&
+ echo "From $pwd/." > expect.err.2 &&
+ echo " $head1..$head2 master -> origin/master" >> expect.err.2 &&
+ cat expect.err.sub >> expect.err.2 &&
+ tail -2 expect.err >> expect.err.2 &&
+ (
+ cd downstream &&
+ git fetch >../actual.out 2>../actual.err
+ ) &&
+ test_cmp expect.err.2 actual.err &&
+ test_cmp expect.out actual.out
+'
+
+test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no new commits are fetched in the superproject (and ignores config)" '
+ add_upstream_commit &&
+ (
+ cd submodule &&
+ (
+ cd deepsubmodule &&
+ git fetch &&
+ git checkout -q FETCH_HEAD
+ ) &&
+ head1=$(git rev-parse --short HEAD^) &&
+ git add deepsubmodule &&
+ git commit -m "new deepsubmodule"
+ head2=$(git rev-parse --short HEAD) &&
+ echo "From $pwd/submodule" > ../expect.err.sub &&
+ echo " $head1..$head2 master -> origin/master" >> ../expect.err.sub
+ ) &&
+ (
+ cd downstream &&
+ git config fetch.recurseSubmodules true &&
+ git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err &&
+ git config --unset fetch.recurseSubmodules
+ ) &&
+ ! test -s actual.out &&
+ ! test -s actual.err
+'
+
+test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necessary (and ignores config)" '
+ head1=$(git rev-parse --short HEAD) &&
+ git add submodule &&
+ git commit -m "new submodule" &&
+ head2=$(git rev-parse --short HEAD) &&
+ tail -2 expect.err > expect.err.deepsub &&
+ echo "From $pwd/." > expect.err &&
+ echo " $head1..$head2 master -> origin/master" >> expect.err
+ cat expect.err.sub >> expect.err &&
+ cat expect.err.deepsub >> expect.err &&
+ (
+ cd downstream &&
+ git config fetch.recurseSubmodules false &&
+ (
+ cd submodule &&
+ git config -f .gitmodules submodule.deepsubmodule.fetchRecursive false
+ ) &&
+ git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err &&
+ git config --unset fetch.recurseSubmodules
+ (
+ cd submodule &&
+ git config --unset -f .gitmodules submodule.deepsubmodule.fetchRecursive
+ )
+ ) &&
+ test_cmp expect.out actual.out &&
+ test_cmp expect.err actual.err
+'
+
+test_expect_success "'--recurse-submodules=on-demand' stops when no new submodule commits are found in the superproject (and ignores config)" '
+ add_upstream_commit &&
+ head1=$(git rev-parse --short HEAD) &&
+ echo a >> file &&
+ git add file &&
+ git commit -m "new file" &&
+ head2=$(git rev-parse --short HEAD) &&
+ echo "From $pwd/." > expect.err.file &&
+ echo " $head1..$head2 master -> origin/master" >> expect.err.file &&
+ (
+ cd downstream &&
+ git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err
+ ) &&
+ ! test -s actual.out &&
+ test_cmp expect.err.file actual.err
+'
+
+test_expect_success "'fetch.recurseSubmodules=on-demand' overrides global config" '
+ (
+ cd downstream &&
+ git fetch --recurse-submodules
+ ) &&
+ add_upstream_commit &&
+ git config --global fetch.recurseSubmodules false &&
+ head1=$(git rev-parse --short HEAD) &&
+ git add submodule &&
+ git commit -m "new submodule" &&
+ head2=$(git rev-parse --short HEAD) &&
+ echo "From $pwd/." > expect.err.2 &&
+ echo " $head1..$head2 master -> origin/master" >> expect.err.2
+ head -2 expect.err >> expect.err.2 &&
+ (
+ cd downstream &&
+ git config fetch.recurseSubmodules on-demand &&
+ git fetch >../actual.out 2>../actual.err
+ ) &&
+ git config --global --unset fetch.recurseSubmodules &&
+ (
+ cd downstream &&
+ git config --unset fetch.recurseSubmodules
+ ) &&
+ test_cmp expect.out.sub actual.out &&
+ test_cmp expect.err.2 actual.err
+'
+
+test_expect_success "'submodule.<sub>.fetchRecurseSubmodules=on-demand' overrides fetch.recurseSubmodules" '
+ (
+ cd downstream &&
+ git fetch --recurse-submodules
+ ) &&
+ add_upstream_commit &&
+ git config fetch.recurseSubmodules false &&
+ head1=$(git rev-parse --short HEAD) &&
+ git add submodule &&
+ git commit -m "new submodule" &&
+ head2=$(git rev-parse --short HEAD) &&
+ echo "From $pwd/." > expect.err.2 &&
+ echo " $head1..$head2 master -> origin/master" >> expect.err.2
+ head -2 expect.err >> expect.err.2 &&
+ (
+ cd downstream &&
+ git config submodule.submodule.fetchRecurseSubmodules on-demand &&
+ git fetch >../actual.out 2>../actual.err
+ ) &&
+ git config --unset fetch.recurseSubmodules &&
+ (
+ cd downstream &&
+ git config --unset submodule.submodule.fetchRecurseSubmodules
+ ) &&
+ test_cmp expect.out.sub actual.out &&
+ test_cmp expect.err.2 actual.err
+'
+
+test_expect_success "don't fetch submodule when newly recorded commits are already present" '
+ (
+ cd submodule &&
+ git checkout -q HEAD^^
+ ) &&
+ head1=$(git rev-parse --short HEAD) &&
+ git add submodule &&
+ git commit -m "submodule rewound" &&
+ head2=$(git rev-parse --short HEAD) &&
+ echo "From $pwd/." > expect.err &&
+ echo " $head1..$head2 master -> origin/master" >> expect.err &&
+ (
+ cd downstream &&
+ git fetch >../actual.out 2>../actual.err
+ ) &&
+ ! test -s actual.out &&
+ test_cmp expect.err actual.err
+'
+
test_done
)
'
+test_expect_success SANITY 'git clean -d with an unreadable empty directory' '
+ mkdir foo &&
+ chmod a= foo &&
+ git clean -dfx foo &&
+ ! test -d foo
+'
+
test_done
test_expect_success '"git submodule sync" should update submodule URLs' '
(cd super-clone &&
- git pull &&
+ git pull --no-recurse-submodules &&
git submodule sync
) &&
test -d "$(git config -f super-clone/submodule/.git/config \
# History setup
#
-# b
-# / \
-# a d
-# \ /
-# c
+# b
+# / \
+# init -- a d
+# \ \ /
+# g c
#
# a in the main repository records to sub-a in the submodule and
# analogous b and c. d should be automatically found by merging c into
git add file-a &&
git commit -m "sub-a" &&
git branch sub-a) &&
+ git commit --allow-empty -m init &&
+ git branch init &&
git add sub &&
git commit -m "a" &&
git branch a &&
git checkout -b sub-d sub-b &&
git merge sub-c) &&
git commit -a -m "d" &&
- git branch test b)
+ git branch test b &&
+
+ git checkout -b g init &&
+ (cd sub &&
+ git checkout -b sub-g sub-c) &&
+ git add sub &&
+ git commit -a -m "g")
'
test_expect_success 'merge with one side as a fast-forward of the other' '
test_must_fail git merge f)
'
+
+# Check that the conflicting submodule is detected when it is
+# in the common ancestor. status should be 'U00...00"
+test_expect_success 'git submodule status should display the merge conflict properly with merge base' '
+ (cd merge-search &&
+ cat >.gitmodules <<EOF &&
+[submodule "sub"]
+ path = sub
+ url = $TRASH_DIRECTORY/sub
+EOF
+ cat >expect <<EOF &&
+U0000000000000000000000000000000000000000 sub
+EOF
+ git submodule status > actual &&
+ test_cmp expect actual &&
+ git reset --hard)
+'
+
+# Check that the conflicting submodule is detected when it is
+# not in the common ancestor. status should be 'U00...00"
+test_expect_success 'git submodule status should display the merge conflict properly without merge-base' '
+ (cd merge-search &&
+ git checkout -b test-no-merge-base g &&
+ test_must_fail git merge b &&
+ cat >.gitmodules <<EOF &&
+[submodule "sub"]
+ path = sub
+ url = $TRASH_DIRECTORY/sub
+EOF
+ cat >expect <<EOF &&
+U0000000000000000000000000000000000000000 sub
+EOF
+ git submodule status > actual &&
+ test_cmp expect actual &&
+ git reset --hard)
+'
+
+
test_expect_success 'merging with a modify/modify conflict between merge bases' '
git reset --hard HEAD &&
git checkout -b test2 c &&
)
'
+apos="'";
+test_expect_success 'submodule update does not fetch already present commits' '
+ (cd submodule &&
+ echo line3 >> file &&
+ git add file &&
+ test_tick &&
+ git commit -m "upstream line3"
+ ) &&
+ (cd super/submodule &&
+ head=$(git rev-parse --verify HEAD) &&
+ echo "Submodule path ${apos}submodule$apos: checked out $apos$head$apos" > ../../expected &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ git submodule update > ../actual 2> ../actual.err
+ ) &&
+ test_cmp expected actual &&
+ ! test -s actual.err
+'
+
test_expect_success 'submodule update --rebase staying on master' '
(cd super/submodule &&
git checkout master
)
'
+test_expect_success 'option automkdirs set to false' '
+ (
+ git svn init "$svnrepo" cloned-no-mkdirs &&
+ cd cloned-no-mkdirs &&
+ git config svn-remote.svn.automkdirs false &&
+ git svn fetch &&
+ for i in a b c d d/e d/e/f "weird file name"
+ do
+ if test -d "$i"
+ then
+ echo >&2 "$i exists"
+ exit 1
+ fi
+ done
+ )
+'
+
test_expect_success 'more emptiness' '
svn_cmd mkdir -m "bang bang" "$svnrepo"/"! !"
'
node_type *foo_nsearch(struct trp_root \*treap, node_type \*key)::
- Like `foo_search`, but if if the key is missing return what
+ Like `foo_search`, but if the key is missing return what
would be key's successor, were key in treap (NULL if no
successor).