mirror of
https://github.com/git/git.git
synced 2026-04-02 13:00:08 +02:00
Merge branch 'master' of git://repo.or.cz/alt-git
This commit is contained in:
28
Documentation/RelNotes-1.6.2.3.txt
Normal file
28
Documentation/RelNotes-1.6.2.3.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
GIT v1.6.2.3 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.6.2.2
|
||||
--------------------
|
||||
|
||||
* Setting an octal mode value to core.sharedrepository configuration to
|
||||
restrict access to the repository to group members did not work as
|
||||
advertised.
|
||||
|
||||
* A fairly large and trivial memory leak while rev-list shows list of
|
||||
reachable objects has been identified and plugged.
|
||||
|
||||
* "git-commit --interactive" did not abort when underlying "git-add -i"
|
||||
signaled a failure.
|
||||
|
||||
* git-repack (invoked from git-gc) did not work as nicely as it should in
|
||||
a repository that borrows objects from neighbours via alternates
|
||||
mechanism especially when some packs are marked with the ".keep" flag
|
||||
to prevent them from being repacked.
|
||||
|
||||
Many small documentation updates are included as well.
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
echo O=$(git describe maint)
|
||||
O=v1.6.2.2-41-gbff82d0
|
||||
git shortlog --no-merges $O..maint
|
||||
@@ -40,6 +40,9 @@ Updates since v1.6.2
|
||||
* many uses of lstat(2) in the codepath for "git checkout" have been
|
||||
optimized out.
|
||||
|
||||
* pruning reflog entries that are unreachable from the tip of the ref
|
||||
during "git reflog prune" (hence "git gc") was very inefficient.
|
||||
|
||||
(usability, bells and whistles)
|
||||
|
||||
* rsync:/path/to/repo can be used to run git over rsync for local
|
||||
@@ -56,7 +59,7 @@ Updates since v1.6.2
|
||||
spelled as "--format=<style>". In addition, --format=%formatstring
|
||||
is a short-hand for --pretty=tformat:%formatstring.
|
||||
|
||||
* "--oneline" is a synonym for "--pretty=oneline --abbrev=commit".
|
||||
* "--oneline" is a synonym for "--pretty=oneline --abbrev-commit".
|
||||
|
||||
* If you realize that you botched the patch when you are editing hunks
|
||||
with the 'edit' action in git-add -i/-p, you can abort the editor to
|
||||
@@ -66,6 +69,10 @@ Updates since v1.6.2
|
||||
messages given by "git checkout" and "git status" used to count merge
|
||||
commits; now it doesn't.
|
||||
|
||||
* @{-1} is a new way to refer to the last branch you were on introduced in
|
||||
1.6.2, but the initial implementation did not teach this to a few
|
||||
commands. Now the syntax works with "branch -m @{-1} newname".
|
||||
|
||||
* git-archive learned --output=<file> option.
|
||||
|
||||
* git-bisect shows not just the number of remaining commits whose goodness
|
||||
@@ -88,10 +95,16 @@ Updates since v1.6.2
|
||||
|
||||
* git-format-patch can be told to produce deep or shallow message threads.
|
||||
|
||||
* git-format-patch can be told to always add sign-off with a configuration
|
||||
variable.
|
||||
|
||||
* git-format-patch learned format.headers configuration to add extra
|
||||
header fields to the output. This behaviour is similar to the existing
|
||||
--add-header=<header> option of the command.
|
||||
|
||||
* git-format-patch gives human readable names to the attached files, when
|
||||
told to send patches as attachments.
|
||||
|
||||
* git-grep learned to highlight the found substrings in color.
|
||||
|
||||
* git-imap-send learned to work around Thunderbird's inability to easily
|
||||
@@ -105,11 +118,6 @@ Updates since v1.6.2
|
||||
|
||||
* Output from git-remote command has been vastly improved.
|
||||
|
||||
* git-repack (invoked from git-gc) did not work as nicely as it should in
|
||||
a repository that borrows objects from neighbours via alternates
|
||||
mechanism especially when some packs are marked with the ".keep" flag
|
||||
to prevent them from being repacked.
|
||||
|
||||
* git-send-email learned --confirm option to review the Cc: list before
|
||||
sending the messages out.
|
||||
|
||||
@@ -141,11 +149,23 @@ v1.6.2.X series.
|
||||
* The initial checkout did not read the attributes from the .gitattribute
|
||||
file that is being checked out.
|
||||
|
||||
* "git-checkout <tree-ish> <submodule>" did not update the index entry at
|
||||
the named path; it now does.
|
||||
|
||||
* git-gc spent excessive amount of time to decide if an object appears
|
||||
in a locally existing pack (if needed, backport by merging 69e020a).
|
||||
|
||||
* "git-ls-tree" and "git-diff-tree" used a pathspec correctly when
|
||||
deciding to descend into a subdirectory but they did not match the
|
||||
individual paths correctly. This caused pathspecs "abc/d ab" to match
|
||||
"abc/0" ("abc/d" made them decide to descend into the directory "abc/",
|
||||
and then "ab" incorrectly matched "abc/0" when it shouldn't).
|
||||
|
||||
* "git-merge-recursive" was broken when a submodule entry was involved in
|
||||
a criss-cross merge situation.
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
O=v1.6.2.2-403-g8130949
|
||||
O=v1.6.2.2-484-g796b137
|
||||
echo O=$(git describe master)
|
||||
git shortlog --no-merges $O..master ^maint
|
||||
|
||||
@@ -480,7 +480,7 @@ branch.<name>.remote::
|
||||
branch.<name>.merge::
|
||||
Defines, together with branch.<name>.remote, the upstream branch
|
||||
for the given branch. It tells 'git-fetch'/'git-pull' which
|
||||
branch to merge from.
|
||||
branch to merge and can also affect 'git-push' (see push.default).
|
||||
When in branch <name>, it tells 'git-fetch' the default
|
||||
refspec to be marked for merging in FETCH_HEAD. The value is
|
||||
handled like the remote part of a refspec, and must match a
|
||||
@@ -715,6 +715,13 @@ format.thread::
|
||||
A true boolean value is the same as `shallow`, and a false
|
||||
value disables threading.
|
||||
|
||||
format.signoff::
|
||||
A boolean value which lets you enable the `-s/--signoff` option of
|
||||
format-patch by default. *Note:* Adding the Signed-off-by: line to a
|
||||
patch should be a conscious act and means that you certify you have
|
||||
the rights to submit this work under the same open source license.
|
||||
Please see the 'SubmittingPatches' document for further discussion.
|
||||
|
||||
gc.aggressiveWindow::
|
||||
The window size parameter used in the delta compression
|
||||
algorithm used by 'git-gc --aggressive'. This defaults
|
||||
|
||||
@@ -16,6 +16,7 @@ body blockquote {
|
||||
html body {
|
||||
margin: 1em 5% 1em 5%;
|
||||
line-height: 1.2;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
body div {
|
||||
@@ -128,6 +129,15 @@ body pre {
|
||||
|
||||
tt.literal, code.literal {
|
||||
color: navy;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
code.literal:before { content: "'"; }
|
||||
code.literal:after { content: "'"; }
|
||||
|
||||
em {
|
||||
font-style: italic;
|
||||
color: #064;
|
||||
}
|
||||
|
||||
div.literallayout p {
|
||||
@@ -137,7 +147,6 @@ div.literallayout p {
|
||||
|
||||
div.literallayout {
|
||||
font-family: monospace;
|
||||
# margin: 0.5em 10% 0.5em 1em;
|
||||
margin: 0em;
|
||||
color: navy;
|
||||
border: 1px solid silver;
|
||||
@@ -187,7 +196,8 @@ dt {
|
||||
}
|
||||
|
||||
dt span.term {
|
||||
font-style: italic;
|
||||
font-style: normal;
|
||||
color: navy;
|
||||
}
|
||||
|
||||
div.variablelist dd p {
|
||||
|
||||
@@ -7,7 +7,9 @@ git-check-ref-format - Ensures that a reference name is well formed
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git check-ref-format' <refname>
|
||||
'git check-ref-format' [--branch] <branchname-shorthand>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -30,7 +32,11 @@ imposes the following rules on how references are named:
|
||||
caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
|
||||
or open bracket `[` anywhere.
|
||||
|
||||
. They cannot end with a slash `/`.
|
||||
. They cannot end with a slash `/` nor a dot `.`.
|
||||
|
||||
. They cannot end with the sequence `.lock`.
|
||||
|
||||
. They cannot contain a sequence `@{`.
|
||||
|
||||
These rules make it easy for shell script based tools to parse
|
||||
reference names, pathname expansion by the shell when a reference name is used
|
||||
@@ -49,6 +55,18 @@ reference name expressions (see linkgit:git-rev-parse[1]):
|
||||
It may also be used to select a specific object such as with
|
||||
'git-cat-file': "git cat-file blob v1.3.3:refs.c".
|
||||
|
||||
. at-open-brace `@{` is used as a notation to access a reflog entry.
|
||||
|
||||
With the `--branch` option, it expands a branch name shorthand and
|
||||
prints the name of the branch the shorthand refers to.
|
||||
|
||||
EXAMPLE
|
||||
-------
|
||||
|
||||
git check-ref-format --branch @{-1}::
|
||||
|
||||
Print the name of the previous branch.
|
||||
|
||||
|
||||
GIT
|
||||
---
|
||||
|
||||
@@ -126,9 +126,13 @@ the conflicted merge in the specified paths.
|
||||
<new_branch>::
|
||||
Name for the new branch.
|
||||
|
||||
<tree-ish>::
|
||||
Tree to checkout from (when paths are given). If not specified,
|
||||
the index will be used.
|
||||
|
||||
<branch>::
|
||||
Branch to checkout; may be any object ID that resolves to a
|
||||
commit. Defaults to HEAD.
|
||||
Branch to checkout (when no paths are given); may be any object
|
||||
ID that resolves to a commit. Defaults to HEAD.
|
||||
+
|
||||
When this parameter names a non-branch (but still a valid commit object),
|
||||
your HEAD becomes 'detached'.
|
||||
@@ -191,7 +195,7 @@ $ git checkout hello.c <3>
|
||||
+
|
||||
<1> switch branch
|
||||
<2> take a file out of another commit
|
||||
<3> restore hello.c from HEAD of current branch
|
||||
<3> restore hello.c from the index
|
||||
+
|
||||
If you have an unfortunate branch that is named `hello.c`, this
|
||||
step would be confused as an instruction to switch to that branch.
|
||||
|
||||
@@ -205,6 +205,7 @@ more than one.
|
||||
numbered = auto
|
||||
cc = <email>
|
||||
attach [ = mime-boundary-string ]
|
||||
signoff = true
|
||||
------------
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ problem by stashing the refs in a single file,
|
||||
traditional `$GIT_DIR/refs` hierarchy, it is looked up in this
|
||||
file and used if found.
|
||||
|
||||
Subsequent updates to branches always creates new file under
|
||||
Subsequent updates to branches always create new files under
|
||||
`$GIT_DIR/refs` hierarchy.
|
||||
|
||||
A recommended practice to deal with a repository with too many
|
||||
@@ -35,7 +35,7 @@ occasionally run `git pack-refs \--prune`. Tags are by
|
||||
definition stationary and are not expected to change. Branch
|
||||
heads will be packed with the initial `pack-refs --all`, but
|
||||
only the currently active branch heads will become unpacked,
|
||||
and next `pack-refs` (without `--all`) will leave them
|
||||
and the next `pack-refs` (without `--all`) will leave them
|
||||
unpacked.
|
||||
|
||||
|
||||
|
||||
@@ -39,13 +39,13 @@ OPTIONS
|
||||
Composing
|
||||
~~~~~~~~~
|
||||
|
||||
--bcc::
|
||||
--bcc=<address>::
|
||||
Specify a "Bcc:" value for each email. Default is the value of
|
||||
'sendemail.bcc'.
|
||||
+
|
||||
The --bcc option must be repeated for each user you want on the bcc list.
|
||||
|
||||
--cc::
|
||||
--cc=<address>::
|
||||
Specify a starting "Cc:" value for each email.
|
||||
Default is the value of 'sendemail.cc'.
|
||||
+
|
||||
@@ -68,24 +68,24 @@ and In-Reply-To headers will be used unless they are removed.
|
||||
+
|
||||
Missing From or In-Reply-To headers will be prompted for.
|
||||
|
||||
--from::
|
||||
--from=<address>::
|
||||
Specify the sender of the emails. This will default to
|
||||
the value GIT_COMMITTER_IDENT, as returned by "git var -l".
|
||||
The user will still be prompted to confirm this entry.
|
||||
|
||||
--in-reply-to::
|
||||
--in-reply-to=<identifier>::
|
||||
Specify the contents of the first In-Reply-To header.
|
||||
Subsequent emails will refer to the previous email
|
||||
instead of this if --chain-reply-to is set (the default)
|
||||
Only necessary if --compose is also set. If --compose
|
||||
is not set, this will be prompted for.
|
||||
|
||||
--subject::
|
||||
--subject=<string>::
|
||||
Specify the initial subject of the email thread.
|
||||
Only necessary if --compose is also set. If --compose
|
||||
is not set, this will be prompted for.
|
||||
|
||||
--to::
|
||||
--to=<address>::
|
||||
Specify the primary recipient of the emails generated. Generally, this
|
||||
will be the upstream maintainer of the project involved. Default is the
|
||||
value of the 'sendemail.to' configuration value; if that is unspecified,
|
||||
@@ -97,7 +97,7 @@ The --to option must be repeated for each user you want on the to list.
|
||||
Sending
|
||||
~~~~~~~
|
||||
|
||||
--envelope-sender::
|
||||
--envelope-sender=<address>::
|
||||
Specify the envelope sender used to send the emails.
|
||||
This is useful if your default address is not the address that is
|
||||
subscribed to a list. If you use the sendmail binary, you must have
|
||||
@@ -105,12 +105,12 @@ Sending
|
||||
the 'sendemail.envelopesender' configuration variable; if that is
|
||||
unspecified, choosing the envelope sender is left to your MTA.
|
||||
|
||||
--smtp-encryption::
|
||||
--smtp-encryption=<encryption>::
|
||||
Specify the encryption to use, either 'ssl' or 'tls'. Any other
|
||||
value reverts to plain SMTP. Default is the value of
|
||||
'sendemail.smtpencryption'.
|
||||
|
||||
--smtp-pass::
|
||||
--smtp-pass[=<password>]::
|
||||
Password for SMTP-AUTH. The argument is optional: If no
|
||||
argument is specified, then the empty string is used as
|
||||
the password. Default is the value of 'sendemail.smtppass',
|
||||
@@ -122,7 +122,7 @@ or on the command line. If a username has been specified (with
|
||||
specified (with '--smtp-pass' or 'sendemail.smtppass'), then the
|
||||
user is prompted for a password while the input is masked for privacy.
|
||||
|
||||
--smtp-server::
|
||||
--smtp-server=<host>::
|
||||
If set, specifies the outgoing SMTP server to use (e.g.
|
||||
`smtp.example.com` or a raw IP address). Alternatively it can
|
||||
specify a full pathname of a sendmail-like program instead;
|
||||
@@ -132,7 +132,7 @@ user is prompted for a password while the input is masked for privacy.
|
||||
`/usr/lib/sendmail` if such program is available, or
|
||||
`localhost` otherwise.
|
||||
|
||||
--smtp-server-port::
|
||||
--smtp-server-port=<port>::
|
||||
Specifies a port different from the default port (SMTP
|
||||
servers typically listen to smtp port 25 and ssmtp port
|
||||
465). This can be set with 'sendemail.smtpserverport'.
|
||||
@@ -140,7 +140,7 @@ user is prompted for a password while the input is masked for privacy.
|
||||
--smtp-ssl::
|
||||
Legacy alias for '--smtp-encryption ssl'.
|
||||
|
||||
--smtp-user::
|
||||
--smtp-user=<user>::
|
||||
Username for SMTP-AUTH. Default is the value of 'sendemail.smtpuser';
|
||||
if a username is not specified (with '--smtp-user' or 'sendemail.smtpuser'),
|
||||
then authentication is not attempted.
|
||||
@@ -149,13 +149,13 @@ user is prompted for a password while the input is masked for privacy.
|
||||
Automating
|
||||
~~~~~~~~~~
|
||||
|
||||
--cc-cmd::
|
||||
--cc-cmd=<command>::
|
||||
Specify a command to execute once per patch file which
|
||||
should generate patch file specific "Cc:" entries.
|
||||
Output of this command must be single email address per line.
|
||||
Default is the value of 'sendemail.cccmd' configuration value.
|
||||
|
||||
--[no-]chain-reply-to::
|
||||
--[no-]chain-reply-to=<identifier>::
|
||||
If this is set, each email will be sent as a reply to the previous
|
||||
email sent. If disabled with "--no-chain-reply-to", all emails after
|
||||
the first will be sent as replies to the first email sent. When using
|
||||
@@ -163,7 +163,7 @@ Automating
|
||||
entire patch series. Default is the value of the 'sendemail.chainreplyto'
|
||||
configuration value; if that is unspecified, default to --chain-reply-to.
|
||||
|
||||
--identity::
|
||||
--identity=<identity>::
|
||||
A configuration identity. When given, causes values in the
|
||||
'sendemail.<identity>' subsection to take precedence over
|
||||
values in the 'sendemail' section. The default identity is
|
||||
@@ -174,7 +174,7 @@ Automating
|
||||
cc list. Default is the value of 'sendemail.signedoffbycc' configuration
|
||||
value; if that is unspecified, default to --signed-off-by-cc.
|
||||
|
||||
--suppress-cc::
|
||||
--suppress-cc=<category>::
|
||||
Specify an additional category of recipients to suppress the
|
||||
auto-cc of:
|
||||
+
|
||||
@@ -211,7 +211,7 @@ specified, as well as 'body' if --no-signed-off-cc is specified.
|
||||
Administering
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
--confirm::
|
||||
--confirm=<mode>::
|
||||
Confirm just before sending:
|
||||
+
|
||||
--
|
||||
|
||||
@@ -9,7 +9,7 @@ git - the stupid content tracker
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git' [--version] [--exec-path[=GIT_EXEC_PATH]]
|
||||
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]
|
||||
[-p|--paginate|--no-pager]
|
||||
[--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]
|
||||
[--help] COMMAND [ARGS]
|
||||
@@ -178,6 +178,10 @@ help ...`.
|
||||
environment variable. If no path is given, 'git' will print
|
||||
the current setting and then exit.
|
||||
|
||||
--html-path::
|
||||
Print the path to wherever your git HTML documentation is installed
|
||||
and exit.
|
||||
|
||||
-p::
|
||||
--paginate::
|
||||
Pipe all output into 'less' (or if set, $PAGER).
|
||||
|
||||
@@ -60,9 +60,9 @@ same as in `.gitignore` files; see linkgit:gitignore[5].
|
||||
When deciding what attributes are assigned to a path, git
|
||||
consults `$GIT_DIR/info/attributes` file (which has the highest
|
||||
precedence), `.gitattributes` file in the same directory as the
|
||||
path in question, and its parent directories (the further the
|
||||
directory that contains `.gitattributes` is from the path in
|
||||
question, the lower its precedence).
|
||||
path in question, and its parent directories up to the toplevel of the
|
||||
work tree (the further the directory that contains `.gitattributes`
|
||||
is from the path in question, the lower its precedence).
|
||||
|
||||
If you wish to affect only a single repository (i.e., to assign
|
||||
attributes to files that are particular to one user's workflow), then
|
||||
|
||||
@@ -31,8 +31,8 @@ precedence, the last matching pattern decides the outcome):
|
||||
|
||||
* Patterns read from a `.gitignore` file in the same directory
|
||||
as the path, or in any parent directory, with patterns in the
|
||||
higher level files (up to the root) being overridden by those in
|
||||
lower level files down to the directory containing the file.
|
||||
higher level files (up to the toplevel of the work tree) being overridden
|
||||
by those in lower level files down to the directory containing the file.
|
||||
These patterns match relative to the location of the
|
||||
`.gitignore` file. A project normally includes such
|
||||
`.gitignore` files in its repository, containing patterns for
|
||||
|
||||
@@ -121,6 +121,7 @@ The placeholders are:
|
||||
- '%d': ref names, like the --decorate option of linkgit:git-log[1]
|
||||
- '%e': encoding
|
||||
- '%s': subject
|
||||
- '%f': sanitized subject line, suitable for a filename
|
||||
- '%b': body
|
||||
- '%Cred': switch color to red
|
||||
- '%Cgreen': switch color to green
|
||||
|
||||
@@ -140,38 +140,38 @@ limiting may be applied.
|
||||
--
|
||||
|
||||
-n 'number'::
|
||||
--max-count='number'::
|
||||
--max-count=<number>::
|
||||
|
||||
Limit the number of commits output.
|
||||
|
||||
--skip='number'::
|
||||
--skip=<number>::
|
||||
|
||||
Skip 'number' commits before starting to show the commit output.
|
||||
|
||||
--since='date'::
|
||||
--after='date'::
|
||||
--since=<date>::
|
||||
--after=<date>::
|
||||
|
||||
Show commits more recent than a specific date.
|
||||
|
||||
--until='date'::
|
||||
--before='date'::
|
||||
--until=<date>::
|
||||
--before=<date>::
|
||||
|
||||
Show commits older than a specific date.
|
||||
|
||||
ifdef::git-rev-list[]
|
||||
--max-age='timestamp'::
|
||||
--min-age='timestamp'::
|
||||
--max-age=<timestamp>::
|
||||
--min-age=<timestamp>::
|
||||
|
||||
Limit the commits output to specified time range.
|
||||
endif::git-rev-list[]
|
||||
|
||||
--author='pattern'::
|
||||
--committer='pattern'::
|
||||
--author=<pattern>::
|
||||
--committer=<pattern>::
|
||||
|
||||
Limit the commits output to ones with author/committer
|
||||
header lines that match the specified pattern (regular expression).
|
||||
|
||||
--grep='pattern'::
|
||||
--grep=<pattern>::
|
||||
|
||||
Limit the commits output to ones with log message that
|
||||
matches the specified pattern (regular expression).
|
||||
|
||||
@@ -188,7 +188,7 @@ As you can see, a commit shows who made the latest change, what they
|
||||
did, and why.
|
||||
|
||||
Every commit has a 40-hexdigit id, sometimes called the "object name" or the
|
||||
"SHA1 id", shown on the first line of the "git-show" output. You can usually
|
||||
"SHA-1 id", shown on the first line of the "git show" output. You can usually
|
||||
refer to a commit by a shorter name, such as a tag or a branch name, but this
|
||||
longer name can also be useful. Most importantly, it is a globally unique
|
||||
name for this commit: so if you tell somebody else the object name (for
|
||||
@@ -307,7 +307,7 @@ ref: refs/heads/master
|
||||
Examining an old version without creating a new branch
|
||||
------------------------------------------------------
|
||||
|
||||
The git-checkout command normally expects a branch head, but will also
|
||||
The `git checkout` command normally expects a branch head, but will also
|
||||
accept an arbitrary commit; for example, you can check out the commit
|
||||
referenced by a tag:
|
||||
|
||||
@@ -320,7 +320,7 @@ If you want to create a new branch from this checkout, you may do so
|
||||
HEAD is now at 427abfa... Linux v2.6.17
|
||||
------------------------------------------------
|
||||
|
||||
The HEAD then refers to the SHA1 of the commit instead of to a branch,
|
||||
The HEAD then refers to the SHA-1 of the commit instead of to a branch,
|
||||
and git branch shows that you are no longer on a branch:
|
||||
|
||||
------------------------------------------------
|
||||
@@ -400,7 +400,7 @@ references with the same shorthand name, see the "SPECIFYING
|
||||
REVISIONS" section of linkgit:git-rev-parse[1].
|
||||
|
||||
[[Updating-a-repository-With-git-fetch]]
|
||||
Updating a repository with git-fetch
|
||||
Updating a repository with git fetch
|
||||
------------------------------------
|
||||
|
||||
Eventually the developer cloned from will do additional work in her
|
||||
@@ -427,7 +427,7 @@ $ git fetch linux-nfs
|
||||
-------------------------------------------------
|
||||
|
||||
New remote-tracking branches will be stored under the shorthand name
|
||||
that you gave "git-remote add", in this case linux-nfs:
|
||||
that you gave "git remote add", in this case linux-nfs:
|
||||
|
||||
-------------------------------------------------
|
||||
$ git branch -r
|
||||
@@ -516,7 +516,7 @@ $ git bisect reset
|
||||
|
||||
to return you to the branch you were on before.
|
||||
|
||||
Note that the version which git-bisect checks out for you at each
|
||||
Note that the version which `git bisect` checks out for you at each
|
||||
point is just a suggestion, and you're free to try a different
|
||||
version if you think it would be a good idea. For example,
|
||||
occasionally you may land on a commit that broke something unrelated;
|
||||
@@ -592,11 +592,11 @@ In addition to HEAD, there are several other special names for
|
||||
commits:
|
||||
|
||||
Merges (to be discussed later), as well as operations such as
|
||||
git-reset, which change the currently checked-out commit, generally
|
||||
`git reset`, which change the currently checked-out commit, generally
|
||||
set ORIG_HEAD to the value HEAD had before the current operation.
|
||||
|
||||
The git-fetch operation always stores the head of the last fetched
|
||||
branch in FETCH_HEAD. For example, if you run git fetch without
|
||||
The `git fetch` operation always stores the head of the last fetched
|
||||
branch in FETCH_HEAD. For example, if you run `git fetch` without
|
||||
specifying a local branch as the target of the operation
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -739,7 +739,7 @@ $ git log --pretty=oneline origin..mybranch | wc -l
|
||||
-------------------------------------------------
|
||||
|
||||
Alternatively, you may often see this sort of thing done with the
|
||||
lower-level command linkgit:git-rev-list[1], which just lists the SHA1's
|
||||
lower-level command linkgit:git-rev-list[1], which just lists the SHA-1's
|
||||
of all the given commits:
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -1073,9 +1073,9 @@ $ git diff
|
||||
|
||||
shows the difference between the working tree and the index file.
|
||||
|
||||
Note that "git-add" always adds just the current contents of a file
|
||||
Note that "git add" always adds just the current contents of a file
|
||||
to the index; further changes to the same file will be ignored unless
|
||||
you run git-add on the file again.
|
||||
you run `git add` on the file again.
|
||||
|
||||
When you're ready, just run
|
||||
|
||||
@@ -1136,7 +1136,7 @@ Ignoring files
|
||||
A project will often generate files that you do 'not' want to track with git.
|
||||
This typically includes files generated by a build process or temporary
|
||||
backup files made by your editor. Of course, 'not' tracking files with git
|
||||
is just a matter of 'not' calling `git-add` on them. But it quickly becomes
|
||||
is just a matter of 'not' calling `git add` on them. But it quickly becomes
|
||||
annoying to have these untracked files lying around; e.g. they make
|
||||
`git add .` practically useless, and they keep showing up in the output of
|
||||
`git status`.
|
||||
@@ -1349,7 +1349,7 @@ $ git add file.txt
|
||||
-------------------------------------------------
|
||||
|
||||
the different stages of that file will be "collapsed", after which
|
||||
git-diff will (by default) no longer show diffs for that file.
|
||||
`git diff` will (by default) no longer show diffs for that file.
|
||||
|
||||
[[undoing-a-merge]]
|
||||
Undoing a merge
|
||||
@@ -1446,7 +1446,7 @@ Fixing a mistake by rewriting history
|
||||
|
||||
If the problematic commit is the most recent commit, and you have not
|
||||
yet made that commit public, then you may just
|
||||
<<undoing-a-merge,destroy it using git-reset>>.
|
||||
<<undoing-a-merge,destroy it using `git reset`>>.
|
||||
|
||||
Alternatively, you
|
||||
can edit the working directory and update the index to fix your
|
||||
@@ -1474,7 +1474,7 @@ Checking out an old version of a file
|
||||
|
||||
In the process of undoing a previous bad change, you may find it
|
||||
useful to check out an older version of a particular file using
|
||||
linkgit:git-checkout[1]. We've used git-checkout before to switch
|
||||
linkgit:git-checkout[1]. We've used `git checkout` before to switch
|
||||
branches, but it has quite different behavior if it is given a path
|
||||
name: the command
|
||||
|
||||
@@ -1542,7 +1542,7 @@ $ git gc
|
||||
-------------------------------------------------
|
||||
|
||||
to recompress the archive. This can be very time-consuming, so
|
||||
you may prefer to run git-gc when you are not doing other work.
|
||||
you may prefer to run `git gc` when you are not doing other work.
|
||||
|
||||
|
||||
[[ensuring-reliability]]
|
||||
@@ -1634,7 +1634,7 @@ In some situations the reflog may not be able to save you. For example,
|
||||
suppose you delete a branch, then realize you need the history it
|
||||
contained. The reflog is also deleted; however, if you have not yet
|
||||
pruned the repository, then you may still be able to find the lost
|
||||
commits in the dangling objects that git-fsck reports. See
|
||||
commits in the dangling objects that `git fsck` reports. See
|
||||
<<dangling-objects>> for the details.
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -1676,7 +1676,7 @@ Sharing development with others
|
||||
===============================
|
||||
|
||||
[[getting-updates-With-git-pull]]
|
||||
Getting updates with git-pull
|
||||
Getting updates with git pull
|
||||
-----------------------------
|
||||
|
||||
After you clone a repository and make a few changes of your own, you
|
||||
@@ -1722,7 +1722,7 @@ repository that you pulled from.
|
||||
<<fast-forwards,fast forward>>; instead, your branch will just be
|
||||
updated to point to the latest commit from the upstream branch.)
|
||||
|
||||
The git-pull command can also be given "." as the "remote" repository,
|
||||
The `git pull` command can also be given "." as the "remote" repository,
|
||||
in which case it just merges in a branch from the current repository; so
|
||||
the commands
|
||||
|
||||
@@ -1795,7 +1795,7 @@ Public git repositories
|
||||
Another way to submit changes to a project is to tell the maintainer
|
||||
of that project to pull the changes from your repository using
|
||||
linkgit:git-pull[1]. In the section "<<getting-updates-With-git-pull,
|
||||
Getting updates with git-pull>>" we described this as a way to get
|
||||
Getting updates with `git pull`>>" we described this as a way to get
|
||||
updates from the "main" repository, but it works just as well in the
|
||||
other direction.
|
||||
|
||||
@@ -1847,7 +1847,7 @@ Setting up a public repository
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Assume your personal repository is in the directory ~/proj. We
|
||||
first create a new clone of the repository and tell git-daemon that it
|
||||
first create a new clone of the repository and tell `git daemon` that it
|
||||
is meant to be public:
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -1878,10 +1878,10 @@ repository>>", below.
|
||||
Otherwise, all you need to do is start linkgit:git-daemon[1]; it will
|
||||
listen on port 9418. By default, it will allow access to any directory
|
||||
that looks like a git directory and contains the magic file
|
||||
git-daemon-export-ok. Passing some directory paths as git-daemon
|
||||
git-daemon-export-ok. Passing some directory paths as `git daemon`
|
||||
arguments will further restrict the exports to those paths.
|
||||
|
||||
You can also run git-daemon as an inetd service; see the
|
||||
You can also run `git daemon` as an inetd service; see the
|
||||
linkgit:git-daemon[1] man page for details. (See especially the
|
||||
examples section.)
|
||||
|
||||
@@ -1942,7 +1942,7 @@ or just
|
||||
$ git push ssh://yourserver.com/~you/proj.git master
|
||||
-------------------------------------------------
|
||||
|
||||
As with git-fetch, git-push will complain if this does not result in a
|
||||
As with `git fetch`, `git push` will complain if this does not result in a
|
||||
<<fast-forwards,fast forward>>; see the following section for details on
|
||||
handling this case.
|
||||
|
||||
@@ -1952,7 +1952,7 @@ repository that has a checked-out working tree, but the working tree
|
||||
will not be updated by the push. This may lead to unexpected results if
|
||||
the branch you push to is the currently checked-out branch!
|
||||
|
||||
As with git-fetch, you may also set up configuration options to
|
||||
As with `git fetch`, you may also set up configuration options to
|
||||
save typing; so, for example, after
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -1988,13 +1988,13 @@ error: failed to push to 'ssh://yourserver.com/~you/proj.git'
|
||||
|
||||
This can happen, for example, if you:
|
||||
|
||||
- use `git-reset --hard` to remove already-published commits, or
|
||||
- use `git-commit --amend` to replace already-published commits
|
||||
- use `git reset --hard` to remove already-published commits, or
|
||||
- use `git commit --amend` to replace already-published commits
|
||||
(as in <<fixing-a-mistake-by-rewriting-history>>), or
|
||||
- use `git-rebase` to rebase any already-published commits (as
|
||||
- use `git rebase` to rebase any already-published commits (as
|
||||
in <<using-git-rebase>>).
|
||||
|
||||
You may force git-push to perform the update anyway by preceding the
|
||||
You may force `git push` to perform the update anyway by preceding the
|
||||
branch name with a plus sign:
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -2036,7 +2036,7 @@ advantages over the central shared repository:
|
||||
|
||||
- Git's ability to quickly import and merge patches allows a
|
||||
single maintainer to process incoming changes even at very
|
||||
high rates. And when that becomes too much, git-pull provides
|
||||
high rates. And when that becomes too much, `git pull` provides
|
||||
an easy way for that maintainer to delegate this job to other
|
||||
maintainers while still allowing optional review of incoming
|
||||
changes.
|
||||
@@ -2404,7 +2404,7 @@ use them, and then explain some of the problems that can arise because
|
||||
you are rewriting history.
|
||||
|
||||
[[using-git-rebase]]
|
||||
Keeping a patch series up to date using git-rebase
|
||||
Keeping a patch series up to date using git rebase
|
||||
--------------------------------------------------
|
||||
|
||||
Suppose that you create a branch "mywork" on a remote-tracking branch
|
||||
@@ -2468,9 +2468,9 @@ patches to the new mywork. The result will look like:
|
||||
................................................
|
||||
|
||||
In the process, it may discover conflicts. In that case it will stop
|
||||
and allow you to fix the conflicts; after fixing conflicts, use "git-add"
|
||||
and allow you to fix the conflicts; after fixing conflicts, use `git add`
|
||||
to update the index with those contents, and then, instead of
|
||||
running git-commit, just run
|
||||
running `git commit`, just run
|
||||
|
||||
-------------------------------------------------
|
||||
$ git rebase --continue
|
||||
@@ -2508,7 +2508,7 @@ with
|
||||
$ git tag bad mywork~5
|
||||
-------------------------------------------------
|
||||
|
||||
(Either gitk or git-log may be useful for finding the commit.)
|
||||
(Either gitk or `git log` may be useful for finding the commit.)
|
||||
|
||||
Then check out that commit, edit it, and rebase the rest of the series
|
||||
on top of it (note that we could check out the commit on a temporary
|
||||
@@ -2549,12 +2549,12 @@ $ gitk origin..mywork &
|
||||
|
||||
and browse through the list of patches in the mywork branch using gitk,
|
||||
applying them (possibly in a different order) to mywork-new using
|
||||
cherry-pick, and possibly modifying them as you go using `commit --amend`.
|
||||
cherry-pick, and possibly modifying them as you go using `git commit --amend`.
|
||||
The linkgit:git-gui[1] command may also help as it allows you to
|
||||
individually select diff hunks for inclusion in the index (by
|
||||
right-clicking on the diff hunk and choosing "Stage Hunk for Commit").
|
||||
|
||||
Another technique is to use git-format-patch to create a series of
|
||||
Another technique is to use `git format-patch` to create a series of
|
||||
patches, then reset the state to before the patches:
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -2662,7 +2662,7 @@ you know is that D is bad, that Z is good, and that
|
||||
linkgit:git-bisect[1] identifies C as the culprit, how will you
|
||||
figure out that the problem is due to this change in semantics?
|
||||
|
||||
When the result of a git-bisect is a non-merge commit, you should
|
||||
When the result of a `git bisect` is a non-merge commit, you should
|
||||
normally be able to discover the problem by examining just that commit.
|
||||
Developers can make this easy by breaking their changes into small
|
||||
self-contained commits. That won't help in the case above, however,
|
||||
@@ -2725,7 +2725,7 @@ master branch. In more detail:
|
||||
git fetch and fast-forwards
|
||||
---------------------------
|
||||
|
||||
In the previous example, when updating an existing branch, "git-fetch"
|
||||
In the previous example, when updating an existing branch, "git fetch"
|
||||
checks to make sure that the most recent commit on the remote
|
||||
branch is a descendant of the most recent commit on your copy of the
|
||||
branch before updating your copy of the branch to point at the new
|
||||
@@ -2751,7 +2751,7 @@ resulting in a situation like:
|
||||
o--o--o <-- new head of the branch
|
||||
................................................
|
||||
|
||||
In this case, "git-fetch" will fail, and print out a warning.
|
||||
In this case, "git fetch" will fail, and print out a warning.
|
||||
|
||||
In that case, you can still force git to update to the new head, as
|
||||
described in the following section. However, note that in the
|
||||
@@ -2760,7 +2760,7 @@ unless you've already created a reference of your own pointing to
|
||||
them.
|
||||
|
||||
[[forcing-fetch]]
|
||||
Forcing git-fetch to do non-fast-forward updates
|
||||
Forcing git fetch to do non-fast-forward updates
|
||||
------------------------------------------------
|
||||
|
||||
If git fetch fails because the new head of a branch is not a
|
||||
@@ -2865,8 +2865,8 @@ The Object Database
|
||||
We already saw in <<understanding-commits>> that all commits are stored
|
||||
under a 40-digit "object name". In fact, all the information needed to
|
||||
represent the history of a project is stored in objects with such names.
|
||||
In each case the name is calculated by taking the SHA1 hash of the
|
||||
contents of the object. The SHA1 hash is a cryptographic hash function.
|
||||
In each case the name is calculated by taking the SHA-1 hash of the
|
||||
contents of the object. The SHA-1 hash is a cryptographic hash function.
|
||||
What that means to us is that it is impossible to find two different
|
||||
objects with the same name. This has a number of advantages; among
|
||||
others:
|
||||
@@ -2877,10 +2877,10 @@ others:
|
||||
same content stored in two repositories will always be stored under
|
||||
the same name.
|
||||
- Git can detect errors when it reads an object, by checking that the
|
||||
object's name is still the SHA1 hash of its contents.
|
||||
object's name is still the SHA-1 hash of its contents.
|
||||
|
||||
(See <<object-details>> for the details of the object formatting and
|
||||
SHA1 calculation.)
|
||||
SHA-1 calculation.)
|
||||
|
||||
There are four different types of objects: "blob", "tree", "commit", and
|
||||
"tag".
|
||||
@@ -2926,9 +2926,9 @@ committer Junio C Hamano <gitster@pobox.com> 1187591163 -0700
|
||||
|
||||
As you can see, a commit is defined by:
|
||||
|
||||
- a tree: The SHA1 name of a tree object (as defined below), representing
|
||||
- a tree: The SHA-1 name of a tree object (as defined below), representing
|
||||
the contents of a directory at a certain point in time.
|
||||
- parent(s): The SHA1 name of some number of commits which represent the
|
||||
- parent(s): The SHA-1 name of some number of commits which represent the
|
||||
immediately previous step(s) in the history of the project. The
|
||||
example above has one parent; merge commits may have more than
|
||||
one. A commit with no parents is called a "root" commit, and
|
||||
@@ -2977,13 +2977,13 @@ $ git ls-tree fb3a8bdd0ce
|
||||
------------------------------------------------
|
||||
|
||||
As you can see, a tree object contains a list of entries, each with a
|
||||
mode, object type, SHA1 name, and name, sorted by name. It represents
|
||||
mode, object type, SHA-1 name, and name, sorted by name. It represents
|
||||
the contents of a single directory tree.
|
||||
|
||||
The object type may be a blob, representing the contents of a file, or
|
||||
another tree, representing the contents of a subdirectory. Since trees
|
||||
and blobs, like all other objects, are named by the SHA1 hash of their
|
||||
contents, two trees have the same SHA1 name if and only if their
|
||||
and blobs, like all other objects, are named by the SHA-1 hash of their
|
||||
contents, two trees have the same SHA-1 name if and only if their
|
||||
contents (including, recursively, the contents of all subdirectories)
|
||||
are identical. This allows git to quickly determine the differences
|
||||
between two related tree objects, since it can ignore any entries with
|
||||
@@ -3029,15 +3029,15 @@ currently checked out.
|
||||
Trust
|
||||
~~~~~
|
||||
|
||||
If you receive the SHA1 name of a blob from one source, and its contents
|
||||
If you receive the SHA-1 name of a blob from one source, and its contents
|
||||
from another (possibly untrusted) source, you can still trust that those
|
||||
contents are correct as long as the SHA1 name agrees. This is because
|
||||
the SHA1 is designed so that it is infeasible to find different contents
|
||||
contents are correct as long as the SHA-1 name agrees. This is because
|
||||
the SHA-1 is designed so that it is infeasible to find different contents
|
||||
that produce the same hash.
|
||||
|
||||
Similarly, you need only trust the SHA1 name of a top-level tree object
|
||||
Similarly, you need only trust the SHA-1 name of a top-level tree object
|
||||
to trust the contents of the entire directory that it refers to, and if
|
||||
you receive the SHA1 name of a commit from a trusted source, then you
|
||||
you receive the SHA-1 name of a commit from a trusted source, then you
|
||||
can easily verify the entire history of commits reachable through
|
||||
parents of that commit, and all of those contents of the trees referred
|
||||
to by those commits.
|
||||
@@ -3049,7 +3049,7 @@ that you trust that commit, and the immutability of the history of
|
||||
commits tells others that they can trust the whole history.
|
||||
|
||||
In other words, you can easily validate a whole archive by just
|
||||
sending out a single email that tells the people the name (SHA1 hash)
|
||||
sending out a single email that tells the people the name (SHA-1 hash)
|
||||
of the top commit, and digitally sign that email using something
|
||||
like GPG/PGP.
|
||||
|
||||
@@ -3090,7 +3090,7 @@ How git stores objects efficiently: pack files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Newly created objects are initially created in a file named after the
|
||||
object's SHA1 hash (stored in .git/objects).
|
||||
object's SHA-1 hash (stored in .git/objects).
|
||||
|
||||
Unfortunately this system becomes inefficient once a project has a
|
||||
lot of objects. Try this on an old project:
|
||||
@@ -3131,7 +3131,7 @@ $ git prune
|
||||
|
||||
to remove any of the "loose" objects that are now contained in the
|
||||
pack. This will also remove any unreferenced objects (which may be
|
||||
created when, for example, you use "git-reset" to remove a commit).
|
||||
created when, for example, you use "git reset" to remove a commit).
|
||||
You can verify that the loose objects are gone by looking at the
|
||||
.git/objects directory or by running
|
||||
|
||||
@@ -3160,7 +3160,7 @@ branch still exists, as does everything it pointed to. The branch
|
||||
pointer itself just doesn't, since you replaced it with another one.
|
||||
|
||||
There are also other situations that cause dangling objects. For
|
||||
example, a "dangling blob" may arise because you did a "git-add" of a
|
||||
example, a "dangling blob" may arise because you did a "git add" of a
|
||||
file, but then, before you actually committed it and made it part of the
|
||||
bigger picture, you changed something else in that file and committed
|
||||
that *updated* thing--the old state that you added originally ends up
|
||||
@@ -3210,7 +3210,7 @@ Usually, dangling blobs and trees aren't very interesting. They're
|
||||
almost always the result of either being a half-way mergebase (the blob
|
||||
will often even have the conflict markers from a merge in it, if you
|
||||
have had conflicting merges that you fixed up by hand), or simply
|
||||
because you interrupted a "git-fetch" with ^C or something like that,
|
||||
because you interrupted a "git fetch" with ^C or something like that,
|
||||
leaving _some_ of the new objects in the object database, but just
|
||||
dangling and useless.
|
||||
|
||||
@@ -3225,9 +3225,9 @@ and they'll be gone. But you should only run "git prune" on a quiescent
|
||||
repository--it's kind of like doing a filesystem fsck recovery: you
|
||||
don't want to do that while the filesystem is mounted.
|
||||
|
||||
(The same is true of "git-fsck" itself, btw, but since
|
||||
git-fsck never actually *changes* the repository, it just reports
|
||||
on what it found, git-fsck itself is never "dangerous" to run.
|
||||
(The same is true of "git fsck" itself, btw, but since
|
||||
`git fsck` never actually *changes* the repository, it just reports
|
||||
on what it found, `git fsck` itself is never 'dangerous' to run.
|
||||
Running it while somebody is actually changing the repository can cause
|
||||
confusing and scary messages, but it won't actually do anything bad. In
|
||||
contrast, running "git prune" while somebody is actively changing the
|
||||
@@ -3297,7 +3297,7 @@ $ git hash-object -w somedirectory/myfile
|
||||
------------------------------------------------
|
||||
|
||||
which will create and store a blob object with the contents of
|
||||
somedirectory/myfile, and output the sha1 of that object. if you're
|
||||
somedirectory/myfile, and output the SHA-1 of that object. if you're
|
||||
extremely lucky it might be 4b9458b3786228369c63936db65827de3cc06200, in
|
||||
which case you've guessed right, and the corruption is fixed!
|
||||
|
||||
@@ -3359,7 +3359,7 @@ The index
|
||||
-----------
|
||||
|
||||
The index is a binary file (generally kept in .git/index) containing a
|
||||
sorted list of path names, each with permissions and the SHA1 of a blob
|
||||
sorted list of path names, each with permissions and the SHA-1 of a blob
|
||||
object; linkgit:git-ls-files[1] can show you the contents of the index:
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -3489,14 +3489,14 @@ done
|
||||
|
||||
NOTE: Do not use local URLs here if you plan to publish your superproject!
|
||||
|
||||
See what files `git-submodule` created:
|
||||
See what files `git submodule` created:
|
||||
|
||||
-------------------------------------------------
|
||||
$ ls -a
|
||||
. .. .git .gitmodules a b c d
|
||||
-------------------------------------------------
|
||||
|
||||
The `git-submodule add <repo> <path>` command does a couple of things:
|
||||
The `git submodule add <repo> <path>` command does a couple of things:
|
||||
|
||||
- It clones the submodule from <repo> to the given <path> under the
|
||||
current directory and by default checks out the master branch.
|
||||
@@ -3542,7 +3542,7 @@ init` to add the submodule repository URLs to `.git/config`:
|
||||
$ git submodule init
|
||||
-------------------------------------------------
|
||||
|
||||
Now use `git-submodule update` to clone the repositories and check out the
|
||||
Now use `git submodule update` to clone the repositories and check out the
|
||||
commits specified in the superproject:
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -3552,8 +3552,8 @@ $ ls -a
|
||||
. .. .git a.txt
|
||||
-------------------------------------------------
|
||||
|
||||
One major difference between `git-submodule update` and `git-submodule add` is
|
||||
that `git-submodule update` checks out a specific commit, rather than the tip
|
||||
One major difference between `git submodule update` and `git submodule add` is
|
||||
that `git submodule update` checks out a specific commit, rather than the tip
|
||||
of a branch. It's like checking out a tag: the head is detached, so you're not
|
||||
working on a branch.
|
||||
|
||||
@@ -3754,7 +3754,7 @@ unsaved state that you might want to restore later!) your current
|
||||
index. Normal operation is just
|
||||
|
||||
-------------------------------------------------
|
||||
$ git read-tree <sha1 of tree>
|
||||
$ git read-tree <SHA-1 of tree>
|
||||
-------------------------------------------------
|
||||
|
||||
and your index file will now be equivalent to the tree that you saved
|
||||
@@ -3769,7 +3769,7 @@ You update your working directory from the index by "checking out"
|
||||
files. This is not a very common operation, since normally you'd just
|
||||
keep your files updated, and rather than write to your working
|
||||
directory, you'd tell the index files about the changes in your
|
||||
working directory (i.e. `git-update-index`).
|
||||
working directory (i.e. `git update-index`).
|
||||
|
||||
However, if you decide to jump to a new version, or check out somebody
|
||||
else's version, or just restore a previous tree, you'd populate your
|
||||
@@ -3782,7 +3782,7 @@ $ git checkout-index filename
|
||||
|
||||
or, if you want to check out all of the index, use `-a`.
|
||||
|
||||
NOTE! git-checkout-index normally refuses to overwrite old files, so
|
||||
NOTE! `git checkout-index` normally refuses to overwrite old files, so
|
||||
if you have an old version of the tree already checked out, you will
|
||||
need to use the "-f" flag ('before' the "-a" flag or the filename) to
|
||||
'force' the checkout.
|
||||
@@ -3820,7 +3820,7 @@ $ git commit-tree <tree> -p <parent> [-p <parent2> ..]
|
||||
and then giving the reason for the commit on stdin (either through
|
||||
redirection from a pipe or file, or by just typing it at the tty).
|
||||
|
||||
git-commit-tree will return the name of the object that represents
|
||||
`git commit-tree` will return the name of the object that represents
|
||||
that commit, and you should save it away for later use. Normally,
|
||||
you'd commit a new `HEAD` state, and while git doesn't care where you
|
||||
save the note about that state, in practice we tend to just write the
|
||||
@@ -3889,7 +3889,7 @@ $ git cat-file blob|tree|commit|tag <objectname>
|
||||
|
||||
to show its contents. NOTE! Trees have binary content, and as a result
|
||||
there is a special helper for showing that content, called
|
||||
`git-ls-tree`, which turns the binary content into a more easily
|
||||
`git ls-tree`, which turns the binary content into a more easily
|
||||
readable form.
|
||||
|
||||
It's especially instructive to look at "commit" objects, since those
|
||||
@@ -3978,13 +3978,13 @@ $ git ls-files --unmerged
|
||||
------------------------------------------------
|
||||
|
||||
Each line of the `git ls-files --unmerged` output begins with
|
||||
the blob mode bits, blob SHA1, 'stage number', and the
|
||||
the blob mode bits, blob SHA-1, 'stage number', and the
|
||||
filename. The 'stage number' is git's way to say which tree it
|
||||
came from: stage 1 corresponds to `$orig` tree, stage 2 `HEAD`
|
||||
tree, and stage3 `$target` tree.
|
||||
|
||||
Earlier we said that trivial merges are done inside
|
||||
`git-read-tree -m`. For example, if the file did not change
|
||||
`git read-tree -m`. For example, if the file did not change
|
||||
from `$orig` to `HEAD` nor `$target`, or if the file changed
|
||||
from `$orig` to `HEAD` and `$orig` to `$target` the same way,
|
||||
obviously the final outcome is what is in `HEAD`. What the
|
||||
@@ -4011,20 +4011,20 @@ $ mv -f hello.c~2 hello.c
|
||||
$ git update-index hello.c
|
||||
-------------------------------------------------
|
||||
|
||||
When a path is in the "unmerged" state, running `git-update-index` for
|
||||
When a path is in the "unmerged" state, running `git update-index` for
|
||||
that path tells git to mark the path resolved.
|
||||
|
||||
The above is the description of a git merge at the lowest level,
|
||||
to help you understand what conceptually happens under the hood.
|
||||
In practice, nobody, not even git itself, runs `git-cat-file` three times
|
||||
for this. There is a `git-merge-index` program that extracts the
|
||||
In practice, nobody, not even git itself, runs `git cat-file` three times
|
||||
for this. There is a `git merge-index` program that extracts the
|
||||
stages to temporary files and calls a "merge" script on it:
|
||||
|
||||
-------------------------------------------------
|
||||
$ git merge-index git-merge-one-file hello.c
|
||||
-------------------------------------------------
|
||||
|
||||
and that is what higher level `git-merge -s resolve` is implemented with.
|
||||
and that is what higher level `git merge -s resolve` is implemented with.
|
||||
|
||||
[[hacking-git]]
|
||||
Hacking git
|
||||
@@ -4045,12 +4045,12 @@ objects). There are currently four different object types: "blob",
|
||||
Regardless of object type, all objects share the following
|
||||
characteristics: they are all deflated with zlib, and have a header
|
||||
that not only specifies their type, but also provides size information
|
||||
about the data in the object. It's worth noting that the SHA1 hash
|
||||
about the data in the object. It's worth noting that the SHA-1 hash
|
||||
that is used to name the object is the hash of the original data
|
||||
plus this header, so `sha1sum` 'file' does not match the object name
|
||||
for 'file'.
|
||||
(Historical note: in the dawn of the age of git the hash
|
||||
was the sha1 of the 'compressed' object.)
|
||||
was the SHA-1 of the 'compressed' object.)
|
||||
|
||||
As a result, the general consistency of an object can always be tested
|
||||
independently of the contents or the type of the object: all objects can
|
||||
@@ -4061,7 +4061,7 @@ size> {plus} <byte\0> {plus} <binary object data>.
|
||||
|
||||
The structured objects can further have their structure and
|
||||
connectivity to other objects verified. This is generally done with
|
||||
the `git-fsck` program, which generates a full dependency graph
|
||||
the `git fsck` program, which generates a full dependency graph
|
||||
of all objects, and verifies their internal consistency (in addition
|
||||
to just verifying their superficial consistency through the hash).
|
||||
|
||||
@@ -4120,7 +4120,7 @@ functions like `get_sha1_basic()` or the likes.
|
||||
This is just to get you into the groove for the most libified part of Git:
|
||||
the revision walker.
|
||||
|
||||
Basically, the initial version of `git-log` was a shell script:
|
||||
Basically, the initial version of `git log` was a shell script:
|
||||
|
||||
----------------------------------------------------------------
|
||||
$ git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | \
|
||||
@@ -4129,20 +4129,20 @@ $ git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | \
|
||||
|
||||
What does this mean?
|
||||
|
||||
`git-rev-list` is the original version of the revision walker, which
|
||||
`git rev-list` is the original version of the revision walker, which
|
||||
_always_ printed a list of revisions to stdout. It is still functional,
|
||||
and needs to, since most new Git programs start out as scripts using
|
||||
`git-rev-list`.
|
||||
`git rev-list`.
|
||||
|
||||
`git-rev-parse` is not as important any more; it was only used to filter out
|
||||
`git rev-parse` is not as important any more; it was only used to filter out
|
||||
options that were relevant for the different plumbing commands that were
|
||||
called by the script.
|
||||
|
||||
Most of what `git-rev-list` did is contained in `revision.c` and
|
||||
Most of what `git rev-list` did is contained in `revision.c` and
|
||||
`revision.h`. It wraps the options in a struct named `rev_info`, which
|
||||
controls how and what revisions are walked, and more.
|
||||
|
||||
The original job of `git-rev-parse` is now taken by the function
|
||||
The original job of `git rev-parse` is now taken by the function
|
||||
`setup_revisions()`, which parses the revisions and the common command line
|
||||
options for the revision walker. This information is stored in the struct
|
||||
`rev_info` for later consumption. You can do your own command line option
|
||||
@@ -4155,7 +4155,7 @@ just have a look at the first implementation of `cmd_log()`; call
|
||||
`git show v1.3.0{tilde}155^2{tilde}4` and scroll down to that function (note that you
|
||||
no longer need to call `setup_pager()` directly).
|
||||
|
||||
Nowadays, `git-log` is a builtin, which means that it is _contained_ in the
|
||||
Nowadays, `git log` is a builtin, which means that it is _contained_ in the
|
||||
command `git`. The source side of a builtin is
|
||||
|
||||
- a function called `cmd_<bla>`, typically defined in `builtin-<bla>.c`,
|
||||
@@ -4171,7 +4171,7 @@ since they share quite a bit of code. In that case, the commands which are
|
||||
_not_ named like the `.c` file in which they live have to be listed in
|
||||
`BUILT_INS` in the `Makefile`.
|
||||
|
||||
`git-log` looks more complicated in C than it does in the original script,
|
||||
`git log` looks more complicated in C than it does in the original script,
|
||||
but that allows for a much greater flexibility and performance.
|
||||
|
||||
Here again it is a good point to take a pause.
|
||||
@@ -4182,9 +4182,9 @@ the organization of Git (after you know the basic concepts).
|
||||
So, think about something which you are interested in, say, "how can I
|
||||
access a blob just knowing the object name of it?". The first step is to
|
||||
find a Git command with which you can do it. In this example, it is either
|
||||
`git-show` or `git-cat-file`.
|
||||
`git show` or `git cat-file`.
|
||||
|
||||
For the sake of clarity, let's stay with `git-cat-file`, because it
|
||||
For the sake of clarity, let's stay with `git cat-file`, because it
|
||||
|
||||
- is plumbing, and
|
||||
|
||||
@@ -4198,7 +4198,7 @@ it does.
|
||||
------------------------------------------------------------------
|
||||
git_config(git_default_config);
|
||||
if (argc != 3)
|
||||
usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>");
|
||||
usage("git cat-file [-t|-s|-e|-p|<type>] <sha1>");
|
||||
if (get_sha1(argv[2], sha1))
|
||||
die("Not a valid object name %s", argv[2]);
|
||||
------------------------------------------------------------------
|
||||
@@ -4243,10 +4243,10 @@ To find out how the result can be used, just read on in `cmd_cat_file()`:
|
||||
-----------------------------------
|
||||
|
||||
Sometimes, you do not know where to look for a feature. In many such cases,
|
||||
it helps to search through the output of `git log`, and then `git-show` the
|
||||
it helps to search through the output of `git log`, and then `git show` the
|
||||
corresponding commit.
|
||||
|
||||
Example: If you know that there was some test case for `git-bundle`, but
|
||||
Example: If you know that there was some test case for `git bundle`, but
|
||||
do not remember where it was (yes, you _could_ `git grep bundle t/`, but that
|
||||
does not illustrate the point!):
|
||||
|
||||
@@ -4530,7 +4530,7 @@ The basic requirements:
|
||||
- Whenever possible, section headings should clearly describe the task
|
||||
they explain how to do, in language that requires no more knowledge
|
||||
than necessary: for example, "importing patches into a project" rather
|
||||
than "the git-am command"
|
||||
than "the `git am` command"
|
||||
|
||||
Think about how to create a clear chapter dependency graph that will
|
||||
allow people to get to important topics without necessarily reading
|
||||
|
||||
1
Makefile
1
Makefile
@@ -1193,6 +1193,7 @@ strip: $(PROGRAMS) git$X
|
||||
|
||||
git.o: git.c common-cmds.h GIT-CFLAGS
|
||||
$(QUIET_CC)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
|
||||
'-DGIT_HTML_PATH="$(htmldir_SQ)"' \
|
||||
$(ALL_CFLAGS) -c $(filter %.c,$^)
|
||||
|
||||
git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
|
||||
|
||||
10
branch.c
10
branch.c
@@ -134,16 +134,8 @@ void create_branch(const char *head,
|
||||
char *real_ref, msg[PATH_MAX + 20];
|
||||
struct strbuf ref = STRBUF_INIT;
|
||||
int forcing = 0;
|
||||
int len;
|
||||
|
||||
len = strlen(name);
|
||||
if (interpret_nth_last_branch(name, &ref) != len) {
|
||||
strbuf_reset(&ref);
|
||||
strbuf_add(&ref, name, len);
|
||||
}
|
||||
strbuf_splice(&ref, 0, 0, "refs/heads/", 11);
|
||||
|
||||
if (check_ref_format(ref.buf))
|
||||
if (strbuf_check_branch_ref(&ref, name))
|
||||
die("'%s' is not a valid branch name.", name);
|
||||
|
||||
if (resolve_ref(ref.buf, sha1, 1, NULL)) {
|
||||
|
||||
@@ -121,11 +121,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
die("Couldn't look up commit object for HEAD");
|
||||
}
|
||||
for (i = 0; i < argc; i++, strbuf_release(&bname)) {
|
||||
int len = strlen(argv[i]);
|
||||
|
||||
if (interpret_nth_last_branch(argv[i], &bname) != len)
|
||||
strbuf_add(&bname, argv[i], len);
|
||||
|
||||
strbuf_branchname(&bname, argv[i]);
|
||||
if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {
|
||||
error("Cannot delete the branch '%s' "
|
||||
"which you are currently on.", bname.buf);
|
||||
@@ -468,22 +464,27 @@ static void rename_branch(const char *oldname, const char *newname, int force)
|
||||
struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
|
||||
unsigned char sha1[20];
|
||||
struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
|
||||
int recovery = 0;
|
||||
|
||||
if (!oldname)
|
||||
die("cannot rename the current branch while not on any.");
|
||||
|
||||
strbuf_addf(&oldref, "refs/heads/%s", oldname);
|
||||
if (strbuf_check_branch_ref(&oldref, oldname)) {
|
||||
/*
|
||||
* Bad name --- this could be an attempt to rename a
|
||||
* ref that we used to allow to be created by accident.
|
||||
*/
|
||||
if (resolve_ref(oldref.buf, sha1, 1, NULL))
|
||||
recovery = 1;
|
||||
else
|
||||
die("Invalid branch name: '%s'", oldname);
|
||||
}
|
||||
|
||||
if (check_ref_format(oldref.buf))
|
||||
die("Invalid branch name: %s", oldref.buf);
|
||||
|
||||
strbuf_addf(&newref, "refs/heads/%s", newname);
|
||||
|
||||
if (check_ref_format(newref.buf))
|
||||
die("Invalid branch name: %s", newref.buf);
|
||||
if (strbuf_check_branch_ref(&newref, newname))
|
||||
die("Invalid branch name: '%s'", newname);
|
||||
|
||||
if (resolve_ref(newref.buf, sha1, 1, NULL) && !force)
|
||||
die("A branch named '%s' already exists.", newname);
|
||||
die("A branch named '%s' already exists.", newref.buf + 11);
|
||||
|
||||
strbuf_addf(&logmsg, "Branch: renamed %s to %s",
|
||||
oldref.buf, newref.buf);
|
||||
@@ -492,6 +493,9 @@ static void rename_branch(const char *oldname, const char *newname, int force)
|
||||
die("Branch rename failed");
|
||||
strbuf_release(&logmsg);
|
||||
|
||||
if (recovery)
|
||||
warning("Renamed a misnamed branch '%s' away", oldref.buf + 11);
|
||||
|
||||
/* no need to pass logmsg here as HEAD didn't really move */
|
||||
if (!strcmp(oldname, head) && create_symref("HEAD", newref.buf, NULL))
|
||||
die("Branch renamed to %s, but HEAD is not updated!", newname);
|
||||
|
||||
@@ -5,9 +5,18 @@
|
||||
#include "cache.h"
|
||||
#include "refs.h"
|
||||
#include "builtin.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
if (argc == 3 && !strcmp(argv[1], "--branch")) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
if (strbuf_check_branch_ref(&sb, argv[2]))
|
||||
die("'%s' is not a valid branch name", argv[2]);
|
||||
printf("%s\n", sb.buf + 11);
|
||||
exit(0);
|
||||
}
|
||||
if (argc != 2)
|
||||
usage("git check-ref-format refname");
|
||||
return !!check_ref_format(argv[1]);
|
||||
|
||||
@@ -53,9 +53,6 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
|
||||
int len;
|
||||
struct cache_entry *ce;
|
||||
|
||||
if (S_ISGITLINK(mode))
|
||||
return 0;
|
||||
|
||||
if (S_ISDIR(mode))
|
||||
return READ_TREE_RECURSIVE;
|
||||
|
||||
@@ -353,16 +350,11 @@ struct branch_info {
|
||||
static void setup_branch_path(struct branch_info *branch)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int ret;
|
||||
|
||||
if ((ret = interpret_nth_last_branch(branch->name, &buf))
|
||||
&& ret == strlen(branch->name)) {
|
||||
strbuf_branchname(&buf, branch->name);
|
||||
if (strcmp(buf.buf, branch->name))
|
||||
branch->name = xstrdup(buf.buf);
|
||||
strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
|
||||
} else {
|
||||
strbuf_addstr(&buf, "refs/heads/");
|
||||
strbuf_addstr(&buf, branch->name);
|
||||
}
|
||||
strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
|
||||
branch->path = strbuf_detach(&buf, NULL);
|
||||
}
|
||||
|
||||
@@ -503,10 +495,10 @@ static void update_refs_for_switch(struct checkout_opts *opts,
|
||||
create_symref("HEAD", new->path, msg.buf);
|
||||
if (!opts->quiet) {
|
||||
if (old->path && !strcmp(new->path, old->path))
|
||||
fprintf(stderr, "Already on \"%s\"\n",
|
||||
fprintf(stderr, "Already on '%s'\n",
|
||||
new->name);
|
||||
else
|
||||
fprintf(stderr, "Switched to%s branch \"%s\"\n",
|
||||
fprintf(stderr, "Switched to%s branch '%s'\n",
|
||||
opts->new_branch ? " a new" : "",
|
||||
new->name);
|
||||
}
|
||||
@@ -515,7 +507,7 @@ static void update_refs_for_switch(struct checkout_opts *opts,
|
||||
REF_NODEREF, DIE_ON_ERR);
|
||||
if (!opts->quiet) {
|
||||
if (old->path)
|
||||
fprintf(stderr, "Note: moving to \"%s\" which isn't a local branch\nIf you want to create a new branch from this checkout, you may do so\n(now or later) by using -b with the checkout command again. Example:\n git checkout -b <new_branch_name>\n", new->name);
|
||||
fprintf(stderr, "Note: moving to '%s' which isn't a local branch\nIf you want to create a new branch from this checkout, you may do so\n(now or later) by using -b with the checkout command again. Example:\n git checkout -b <new_branch_name>\n", new->name);
|
||||
describe_detached_head("HEAD is now at", new->commit);
|
||||
}
|
||||
}
|
||||
@@ -738,12 +730,11 @@ no_reference:
|
||||
|
||||
if (opts.new_branch) {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
strbuf_addstr(&buf, "refs/heads/");
|
||||
strbuf_addstr(&buf, opts.new_branch);
|
||||
if (strbuf_check_branch_ref(&buf, opts.new_branch))
|
||||
die("git checkout: we do not like '%s' as a branch name.",
|
||||
opts.new_branch);
|
||||
if (!get_sha1(buf.buf, rev))
|
||||
die("git checkout: branch %s already exists", opts.new_branch);
|
||||
if (check_ref_format(buf.buf))
|
||||
die("git checkout: we do not like '%s' as a branch name.", opts.new_branch);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
|
||||
@@ -224,7 +224,8 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
|
||||
const char **pathspec = NULL;
|
||||
|
||||
if (interactive) {
|
||||
interactive_add(argc, argv, prefix);
|
||||
if (interactive_add(argc, argv, prefix) != 0)
|
||||
die("interactive add failed");
|
||||
if (read_cache_preload(NULL) < 0)
|
||||
die("index file corrupt");
|
||||
commit_style = COMMIT_AS_IS;
|
||||
|
||||
@@ -194,6 +194,8 @@ static int create_default_files(const char *template_path)
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
is_bare_repository_cfg = init_is_bare_repository;
|
||||
|
||||
/* reading existing config may have overwrote it */
|
||||
if (init_shared_repository != -1)
|
||||
shared_repository = init_shared_repository;
|
||||
|
||||
@@ -312,12 +314,15 @@ int init_db(const char *template_dir, unsigned int flags)
|
||||
* and compatibility values for PERM_GROUP and
|
||||
* PERM_EVERYBODY.
|
||||
*/
|
||||
if (shared_repository == PERM_GROUP)
|
||||
if (shared_repository < 0)
|
||||
/* force to the mode value */
|
||||
sprintf(buf, "0%o", -shared_repository);
|
||||
else if (shared_repository == PERM_GROUP)
|
||||
sprintf(buf, "%d", OLD_PERM_GROUP);
|
||||
else if (shared_repository == PERM_EVERYBODY)
|
||||
sprintf(buf, "%d", OLD_PERM_EVERYBODY);
|
||||
else
|
||||
sprintf(buf, "0%o", shared_repository);
|
||||
die("oops");
|
||||
git_config_set("core.sharedrepository", buf);
|
||||
git_config_set("receive.denyNonFastforwards", "true");
|
||||
}
|
||||
@@ -397,6 +402,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
|
||||
usage(init_db_usage);
|
||||
}
|
||||
|
||||
if (init_shared_repository != -1)
|
||||
shared_repository = init_shared_repository;
|
||||
|
||||
/*
|
||||
* GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
|
||||
* without --bare. Catch the error early.
|
||||
|
||||
154
builtin-log.c
154
builtin-log.c
@@ -417,13 +417,6 @@ int cmd_log(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
|
||||
/* format-patch */
|
||||
#define FORMAT_PATCH_NAME_MAX 64
|
||||
|
||||
static int istitlechar(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') || c == '.' || c == '_';
|
||||
}
|
||||
|
||||
static const char *fmt_patch_suffix = ".patch";
|
||||
static int numbered = 0;
|
||||
@@ -465,6 +458,7 @@ static void add_header(const char *value)
|
||||
#define THREAD_SHALLOW 1
|
||||
#define THREAD_DEEP 2
|
||||
static int thread = 0;
|
||||
static int do_signoff = 0;
|
||||
|
||||
static int git_format_config(const char *var, const char *value, void *cb)
|
||||
{
|
||||
@@ -514,96 +508,41 @@ static int git_format_config(const char *var, const char *value, void *cb)
|
||||
thread = git_config_bool(var, value) && THREAD_SHALLOW;
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "format.signoff")) {
|
||||
do_signoff = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_log_config(var, value, cb);
|
||||
}
|
||||
|
||||
|
||||
static const char *get_oneline_for_filename(struct commit *commit,
|
||||
int keep_subject)
|
||||
{
|
||||
static char filename[PATH_MAX];
|
||||
char *sol;
|
||||
int len = 0;
|
||||
int suffix_len = strlen(fmt_patch_suffix) + 1;
|
||||
|
||||
sol = strstr(commit->buffer, "\n\n");
|
||||
if (!sol)
|
||||
filename[0] = '\0';
|
||||
else {
|
||||
int j, space = 0;
|
||||
|
||||
sol += 2;
|
||||
/* strip [PATCH] or [PATCH blabla] */
|
||||
if (!keep_subject && !prefixcmp(sol, "[PATCH")) {
|
||||
char *eos = strchr(sol + 6, ']');
|
||||
if (eos) {
|
||||
while (isspace(*eos))
|
||||
eos++;
|
||||
sol = eos;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0;
|
||||
j < FORMAT_PATCH_NAME_MAX - suffix_len - 5 &&
|
||||
len < sizeof(filename) - suffix_len &&
|
||||
sol[j] && sol[j] != '\n';
|
||||
j++) {
|
||||
if (istitlechar(sol[j])) {
|
||||
if (space) {
|
||||
filename[len++] = '-';
|
||||
space = 0;
|
||||
}
|
||||
filename[len++] = sol[j];
|
||||
if (sol[j] == '.')
|
||||
while (sol[j + 1] == '.')
|
||||
j++;
|
||||
} else
|
||||
space = 1;
|
||||
}
|
||||
while (filename[len - 1] == '.'
|
||||
|| filename[len - 1] == '-')
|
||||
len--;
|
||||
filename[len] = '\0';
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
static FILE *realstdout = NULL;
|
||||
static const char *output_directory = NULL;
|
||||
static int outdir_offset;
|
||||
|
||||
static int reopen_stdout(const char *oneline, int nr, struct rev_info *rev)
|
||||
static int reopen_stdout(struct commit *commit, struct rev_info *rev)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
int len = 0;
|
||||
struct strbuf filename = STRBUF_INIT;
|
||||
int suffix_len = strlen(fmt_patch_suffix) + 1;
|
||||
|
||||
if (output_directory) {
|
||||
len = snprintf(filename, sizeof(filename), "%s",
|
||||
output_directory);
|
||||
if (len >=
|
||||
sizeof(filename) - FORMAT_PATCH_NAME_MAX - suffix_len)
|
||||
strbuf_addstr(&filename, output_directory);
|
||||
if (filename.len >=
|
||||
PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len)
|
||||
return error("name of output directory is too long");
|
||||
if (filename[len - 1] != '/')
|
||||
filename[len++] = '/';
|
||||
if (filename.buf[filename.len - 1] != '/')
|
||||
strbuf_addch(&filename, '/');
|
||||
}
|
||||
|
||||
if (!oneline)
|
||||
len += sprintf(filename + len, "%d", nr);
|
||||
else {
|
||||
len += sprintf(filename + len, "%04d-", nr);
|
||||
len += snprintf(filename + len, sizeof(filename) - len - 1
|
||||
- suffix_len, "%s", oneline);
|
||||
strcpy(filename + len, fmt_patch_suffix);
|
||||
}
|
||||
get_patch_filename(commit, rev->nr, fmt_patch_suffix, &filename);
|
||||
|
||||
if (!DIFF_OPT_TST(&rev->diffopt, QUIET))
|
||||
fprintf(realstdout, "%s\n", filename + outdir_offset);
|
||||
fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
|
||||
|
||||
if (freopen(filename, "w", stdout) == NULL)
|
||||
return error("Cannot open patch file %s",filename);
|
||||
if (freopen(filename.buf, "w", stdout) == NULL)
|
||||
return error("Cannot open patch file %s", filename.buf);
|
||||
|
||||
strbuf_release(&filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -673,7 +612,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
||||
int nr, struct commit **list, struct commit *head)
|
||||
{
|
||||
const char *committer;
|
||||
char *head_sha1;
|
||||
const char *subject_start = NULL;
|
||||
const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
|
||||
const char *msg;
|
||||
@@ -684,21 +622,41 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
||||
const char *encoding = "utf-8";
|
||||
struct diff_options opts;
|
||||
int need_8bit_cte = 0;
|
||||
struct commit *commit = NULL;
|
||||
|
||||
if (rev->commit_format != CMIT_FMT_EMAIL)
|
||||
die("Cover letter needs email format");
|
||||
|
||||
if (!use_stdout && reopen_stdout(numbered_files ?
|
||||
NULL : "cover-letter", 0, rev))
|
||||
committer = git_committer_info(0);
|
||||
|
||||
if (!numbered_files) {
|
||||
/*
|
||||
* We fake a commit for the cover letter so we get the filename
|
||||
* desired.
|
||||
*/
|
||||
commit = xcalloc(1, sizeof(*commit));
|
||||
commit->buffer = xmalloc(400);
|
||||
snprintf(commit->buffer, 400,
|
||||
"tree 0000000000000000000000000000000000000000\n"
|
||||
"parent %s\n"
|
||||
"author %s\n"
|
||||
"committer %s\n\n"
|
||||
"cover letter\n",
|
||||
sha1_to_hex(head->object.sha1), committer, committer);
|
||||
}
|
||||
|
||||
if (!use_stdout && reopen_stdout(commit, rev))
|
||||
return;
|
||||
|
||||
head_sha1 = sha1_to_hex(head->object.sha1);
|
||||
if (commit) {
|
||||
|
||||
log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers,
|
||||
free(commit->buffer);
|
||||
free(commit);
|
||||
}
|
||||
|
||||
log_write_email_headers(rev, head, &subject_start, &extra_headers,
|
||||
&need_8bit_cte);
|
||||
|
||||
committer = git_committer_info(0);
|
||||
|
||||
msg = body;
|
||||
pp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,
|
||||
encoding);
|
||||
@@ -865,13 +823,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
else if (!strcmp(argv[i], "--signoff") ||
|
||||
!strcmp(argv[i], "-s")) {
|
||||
const char *committer;
|
||||
const char *endpos;
|
||||
committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
||||
endpos = strchr(committer, '>');
|
||||
if (!endpos)
|
||||
die("bogus committer info %s", committer);
|
||||
add_signoff = xmemdupz(committer, endpos - committer + 1);
|
||||
do_signoff = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--attach")) {
|
||||
rev.mime_boundary = git_version_string;
|
||||
@@ -925,6 +877,16 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
argc = j;
|
||||
|
||||
if (do_signoff) {
|
||||
const char *committer;
|
||||
const char *endpos;
|
||||
committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
||||
endpos = strchr(committer, '>');
|
||||
if (!endpos)
|
||||
die("bogus committer info %s", committer);
|
||||
add_signoff = xmemdupz(committer, endpos - committer + 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < extra_hdr_nr; i++) {
|
||||
strbuf_addstr(&buf, extra_hdr[i]);
|
||||
strbuf_addch(&buf, '\n');
|
||||
@@ -1058,6 +1020,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
const char *msgid = clean_message_id(in_reply_to);
|
||||
string_list_append(msgid, rev.ref_message_ids);
|
||||
}
|
||||
rev.numbered_files = numbered_files;
|
||||
rev.patch_suffix = fmt_patch_suffix;
|
||||
if (cover_letter) {
|
||||
if (thread)
|
||||
gen_message_id(&rev, "cover");
|
||||
@@ -1106,9 +1070,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
|
||||
}
|
||||
if (!use_stdout && reopen_stdout(numbered_files ? NULL :
|
||||
get_oneline_for_filename(commit, keep_subject),
|
||||
rev.nr, &rev))
|
||||
|
||||
if (!use_stdout && reopen_stdout(numbered_files ? NULL : commit,
|
||||
&rev))
|
||||
die("Failed to create output files");
|
||||
shown = log_tree_commit(&rev, commit);
|
||||
free(commit->buffer);
|
||||
|
||||
@@ -360,9 +360,8 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
||||
const char *ptr;
|
||||
int len, early;
|
||||
|
||||
len = strlen(remote);
|
||||
if (interpret_nth_last_branch(remote, &bname) == len)
|
||||
remote = bname.buf;
|
||||
strbuf_branchname(&bname, remote);
|
||||
remote = bname.buf;
|
||||
|
||||
memset(branch_head, 0, sizeof(branch_head));
|
||||
remote_head = peel_to_type(remote, 0, NULL, OBJ_COMMIT);
|
||||
|
||||
@@ -52,6 +52,7 @@ struct collect_reflog_cb {
|
||||
|
||||
#define INCOMPLETE (1u<<10)
|
||||
#define STUDYING (1u<<11)
|
||||
#define REACHABLE (1u<<12)
|
||||
|
||||
static int tree_is_complete(const unsigned char *sha1)
|
||||
{
|
||||
@@ -209,6 +210,70 @@ static int keep_entry(struct commit **it, unsigned char *sha1)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int unreachable(struct expire_reflog_cb *cb, struct commit *commit, unsigned char *sha1)
|
||||
{
|
||||
/*
|
||||
* We may or may not have the commit yet - if not, look it
|
||||
* up using the supplied sha1.
|
||||
*/
|
||||
if (!commit) {
|
||||
if (is_null_sha1(sha1))
|
||||
return 0;
|
||||
|
||||
commit = lookup_commit_reference_gently(sha1, 1);
|
||||
|
||||
/* Not a commit -- keep it */
|
||||
if (!commit)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reachable from the current ref? Don't prune. */
|
||||
if (commit->object.flags & REACHABLE)
|
||||
return 0;
|
||||
if (in_merge_bases(commit, &cb->ref_commit, 1))
|
||||
return 0;
|
||||
|
||||
/* We can't reach it - prune it. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void mark_reachable(struct commit *commit, unsigned long expire_limit)
|
||||
{
|
||||
/*
|
||||
* We need to compute if commit on either side of an reflog
|
||||
* entry is reachable from the tip of the ref for all entries.
|
||||
* Mark commits that are reachable from the tip down to the
|
||||
* time threashold first; we know a commit marked thusly is
|
||||
* reachable from the tip without running in_merge_bases()
|
||||
* at all.
|
||||
*/
|
||||
struct commit_list *pending = NULL;
|
||||
|
||||
commit_list_insert(commit, &pending);
|
||||
while (pending) {
|
||||
struct commit_list *entry = pending;
|
||||
struct commit_list *parent;
|
||||
pending = entry->next;
|
||||
commit = entry->item;
|
||||
free(entry);
|
||||
if (commit->object.flags & REACHABLE)
|
||||
continue;
|
||||
if (parse_commit(commit))
|
||||
continue;
|
||||
commit->object.flags |= REACHABLE;
|
||||
if (commit->date < expire_limit)
|
||||
continue;
|
||||
parent = commit->parents;
|
||||
while (parent) {
|
||||
commit = parent->item;
|
||||
parent = parent->next;
|
||||
if (commit->object.flags & REACHABLE)
|
||||
continue;
|
||||
commit_list_insert(commit, &pending);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
|
||||
const char *email, unsigned long timestamp, int tz,
|
||||
const char *message, void *cb_data)
|
||||
@@ -230,12 +295,7 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
|
||||
if (timestamp < cb->cmd->expire_unreachable) {
|
||||
if (!cb->ref_commit)
|
||||
goto prune;
|
||||
if (!old && !is_null_sha1(osha1))
|
||||
old = lookup_commit_reference_gently(osha1, 1);
|
||||
if (!new && !is_null_sha1(nsha1))
|
||||
new = lookup_commit_reference_gently(nsha1, 1);
|
||||
if ((old && !in_merge_bases(old, &cb->ref_commit, 1)) ||
|
||||
(new && !in_merge_bases(new, &cb->ref_commit, 1)))
|
||||
if (unreachable(cb, old, osha1) || unreachable(cb, new, nsha1))
|
||||
goto prune;
|
||||
}
|
||||
|
||||
@@ -288,7 +348,11 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
|
||||
cb.ref_commit = lookup_commit_reference_gently(sha1, 1);
|
||||
cb.ref = ref;
|
||||
cb.cmd = cmd;
|
||||
if (cb.ref_commit)
|
||||
mark_reachable(cb.ref_commit, cmd->expire_total);
|
||||
for_each_reflog_ent(ref, expire_reflog_ent, &cb);
|
||||
if (cb.ref_commit)
|
||||
clear_commit_marks(cb.ref_commit, REACHABLE);
|
||||
finish:
|
||||
if (cb.newlog) {
|
||||
if (fclose(cb.newlog)) {
|
||||
|
||||
5
cache.h
5
cache.h
@@ -623,7 +623,8 @@ enum sharedrepo {
|
||||
PERM_EVERYBODY = 0664,
|
||||
};
|
||||
int git_config_perm(const char *var, const char *value);
|
||||
int adjust_shared_perm(const char *path);
|
||||
int set_shared_perm(const char *path, int mode);
|
||||
#define adjust_shared_perm(path) set_shared_perm((path), 0)
|
||||
int safe_create_leading_directories(char *path);
|
||||
int safe_create_leading_directories_const(const char *path);
|
||||
char *enter_repo(char *path, int strict);
|
||||
@@ -679,7 +680,7 @@ extern int read_ref(const char *filename, unsigned char *sha1);
|
||||
extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *);
|
||||
extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
|
||||
extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
|
||||
extern int interpret_nth_last_branch(const char *str, struct strbuf *);
|
||||
extern int interpret_branch_name(const char *str, struct strbuf *);
|
||||
|
||||
extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules);
|
||||
extern const char *ref_rev_parse_rules[];
|
||||
|
||||
@@ -646,7 +646,8 @@ _git_am ()
|
||||
;;
|
||||
--*)
|
||||
__gitcomp "
|
||||
--signoff --utf8 --binary --3way --interactive
|
||||
--3way --committer-date-is-author-date --ignore-date
|
||||
--interactive --keep --no-utf8 --signoff --utf8
|
||||
--whitespace=
|
||||
"
|
||||
return
|
||||
@@ -1870,6 +1871,7 @@ _git ()
|
||||
--bare
|
||||
--version
|
||||
--exec-path
|
||||
--html-path
|
||||
--work-tree=
|
||||
--help
|
||||
"
|
||||
|
||||
@@ -903,9 +903,6 @@ static char *keep_pack(char *curr_index_name)
|
||||
static const char *keep_msg = "fast-import";
|
||||
int keep_fd;
|
||||
|
||||
chmod(pack_data->pack_name, 0444);
|
||||
chmod(curr_index_name, 0444);
|
||||
|
||||
keep_fd = odb_pack_keep(name, sizeof(name), pack_data->sha1);
|
||||
if (keep_fd < 0)
|
||||
die("cannot create keep file");
|
||||
|
||||
@@ -77,7 +77,7 @@ bisect_start() {
|
||||
then
|
||||
# Reset to the rev from where we started.
|
||||
start_head=$(cat "$GIT_DIR/BISECT_START")
|
||||
git checkout "$start_head" || exit
|
||||
git checkout "$start_head" -- || exit
|
||||
else
|
||||
# Get rev from where we start.
|
||||
case "$head" in
|
||||
@@ -370,7 +370,7 @@ bisect_checkout() {
|
||||
_msg="$2"
|
||||
echo "Bisecting: $_msg"
|
||||
mark_expected_rev "$_rev"
|
||||
git checkout -q "$_rev" || exit
|
||||
git checkout -q "$_rev" -- || exit
|
||||
git show-branch "$_rev"
|
||||
}
|
||||
|
||||
@@ -549,7 +549,7 @@ bisect_reset() {
|
||||
*)
|
||||
usage ;;
|
||||
esac
|
||||
git checkout "$branch" && bisect_clean_state
|
||||
git checkout "$branch" -- && bisect_clean_state
|
||||
}
|
||||
|
||||
bisect_clean_state() {
|
||||
|
||||
42
git-pull.sh
42
git-pull.sh
@@ -90,23 +90,31 @@ error_on_no_merge_candidates () {
|
||||
|
||||
curr_branch=${curr_branch#refs/heads/}
|
||||
|
||||
echo "You asked me to pull without telling me which branch you"
|
||||
echo "want to merge with, and 'branch.${curr_branch}.merge' in"
|
||||
echo "your configuration file does not tell me either. Please"
|
||||
echo "name which branch you want to merge on the command line and"
|
||||
echo "try again (e.g. 'git pull <repository> <refspec>')."
|
||||
echo "See git-pull(1) for details on the refspec."
|
||||
echo
|
||||
echo "If you often merge with the same branch, you may want to"
|
||||
echo "configure the following variables in your configuration"
|
||||
echo "file:"
|
||||
echo
|
||||
echo " branch.${curr_branch}.remote = <nickname>"
|
||||
echo " branch.${curr_branch}.merge = <remote-ref>"
|
||||
echo " remote.<nickname>.url = <url>"
|
||||
echo " remote.<nickname>.fetch = <refspec>"
|
||||
echo
|
||||
echo "See git-config(1) for details."
|
||||
if [ -z "$curr_branch" ]; then
|
||||
echo "You are not currently on a branch, so I cannot use any"
|
||||
echo "'branch.<branchname>.merge' in your configuration file."
|
||||
echo "Please specify which branch you want to merge on the command"
|
||||
echo "line and try again (e.g. 'git pull <repository> <refspec>')."
|
||||
echo "See git-pull(1) for details."
|
||||
else
|
||||
echo "You asked me to pull without telling me which branch you"
|
||||
echo "want to merge with, and 'branch.${curr_branch}.merge' in"
|
||||
echo "your configuration file does not tell me either. Please"
|
||||
echo "specify which branch you want to merge on the command line and"
|
||||
echo "try again (e.g. 'git pull <repository> <refspec>')."
|
||||
echo "See git-pull(1) for details."
|
||||
echo
|
||||
echo "If you often merge with the same branch, you may want to"
|
||||
echo "configure the following variables in your configuration"
|
||||
echo "file:"
|
||||
echo
|
||||
echo " branch.${curr_branch}.remote = <nickname>"
|
||||
echo " branch.${curr_branch}.merge = <remote-ref>"
|
||||
echo " remote.<nickname>.url = <url>"
|
||||
echo " remote.<nickname>.fetch = <refspec>"
|
||||
echo
|
||||
echo "See git-config(1) for details."
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
@@ -181,5 +181,5 @@ fi
|
||||
|
||||
case "$no_update_info" in
|
||||
t) : ;;
|
||||
*) git-update-server-info ;;
|
||||
*) git update-server-info ;;
|
||||
esac
|
||||
|
||||
@@ -608,7 +608,7 @@ EOT
|
||||
|
||||
sub ask {
|
||||
my ($prompt, %arg) = @_;
|
||||
my $valid_re = $arg{valid_re} || ""; # "" matches anything
|
||||
my $valid_re = $arg{valid_re};
|
||||
my $default = $arg{default};
|
||||
my $resp;
|
||||
my $i = 0;
|
||||
@@ -624,7 +624,7 @@ sub ask {
|
||||
if ($resp eq '' and defined $default) {
|
||||
return $default;
|
||||
}
|
||||
if ($resp =~ /$valid_re/) {
|
||||
if (!defined $valid_re or $resp =~ /$valid_re/) {
|
||||
return $resp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# Copyright (c) 2007 Lars Hjemli
|
||||
|
||||
USAGE="[--quiet] [--cached] \
|
||||
[add <repo> [-b branch] <path>]|[status|init|update [-i|--init] [-N|--no-fetch]|summary [-n|--summary-limit <n>] [<commit>]] \
|
||||
[add [-b branch] <repo> <path>]|[status|init|update [-i|--init] [-N|--no-fetch]|summary [-n|--summary-limit <n>] [<commit>]] \
|
||||
[--] [<path>...]|[foreach <command>]|[sync [--] [<path>...]]"
|
||||
OPTIONS_SPEC=
|
||||
. git-sh-setup
|
||||
|
||||
5
git.c
5
git.c
@@ -5,7 +5,7 @@
|
||||
#include "run-command.h"
|
||||
|
||||
const char git_usage_string[] =
|
||||
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
|
||||
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
|
||||
|
||||
const char git_more_info_string[] =
|
||||
"See 'git help COMMAND' for more information on a specific command.";
|
||||
@@ -75,6 +75,9 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
|
||||
puts(git_exec_path());
|
||||
exit(0);
|
||||
}
|
||||
} else if (!strcmp(cmd, "--html-path")) {
|
||||
puts(system_path(GIT_HTML_PATH));
|
||||
exit(0);
|
||||
} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
|
||||
use_pager = 1;
|
||||
} else if (!strcmp(cmd, "--no-pager")) {
|
||||
|
||||
25
http-push.c
25
http-push.c
@@ -567,6 +567,10 @@ static void start_put(struct transfer_request *request)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &request->buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, request->buffer.buf.len);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||
#ifndef NO_CURL_IOCTL
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &request->buffer);
|
||||
#endif
|
||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
|
||||
@@ -748,7 +752,6 @@ static void finish_request(struct transfer_request *request)
|
||||
aborted = 1;
|
||||
}
|
||||
} else if (request->state == RUN_FETCH_LOOSE) {
|
||||
fchmod(request->local_fileno, 0444);
|
||||
close(request->local_fileno); request->local_fileno = -1;
|
||||
|
||||
if (request->curl_result != CURLE_OK &&
|
||||
@@ -1267,6 +1270,10 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||
#ifndef NO_CURL_IOCTL
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
|
||||
#endif
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
||||
@@ -1508,6 +1515,10 @@ static void remote_ls(const char *path, int flags,
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||
#ifndef NO_CURL_IOCTL
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
|
||||
#endif
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
||||
@@ -1584,6 +1595,10 @@ static int locking_available(void)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||
#ifndef NO_CURL_IOCTL
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
|
||||
#endif
|
||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url);
|
||||
@@ -1766,6 +1781,10 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||
#ifndef NO_CURL_IOCTL
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
|
||||
#endif
|
||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
|
||||
@@ -1910,6 +1929,10 @@ static void update_remote_info_refs(struct remote_lock *lock)
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, buffer.buf.len);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
|
||||
#ifndef NO_CURL_IOCTL
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &buffer);
|
||||
#endif
|
||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
|
||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
|
||||
|
||||
@@ -231,7 +231,6 @@ static void finish_object_request(struct object_request *obj_req)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
fchmod(obj_req->local, 0444);
|
||||
close(obj_req->local); obj_req->local = -1;
|
||||
|
||||
if (obj_req->http_code == 416) {
|
||||
|
||||
19
http.c
19
http.c
@@ -44,6 +44,25 @@ size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifndef NO_CURL_IOCTL
|
||||
curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
|
||||
{
|
||||
struct buffer *buffer = clientp;
|
||||
|
||||
switch (cmd) {
|
||||
case CURLIOCMD_NOP:
|
||||
return CURLIOE_OK;
|
||||
|
||||
case CURLIOCMD_RESTARTREAD:
|
||||
buffer->posn = 0;
|
||||
return CURLIOE_OK;
|
||||
|
||||
default:
|
||||
return CURLIOE_UNKNOWNCMD;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
|
||||
{
|
||||
size_t size = eltsize * nmemb;
|
||||
|
||||
7
http.h
7
http.h
@@ -37,6 +37,10 @@
|
||||
#define CURLE_HTTP_RETURNED_ERROR CURLE_HTTP_NOT_FOUND
|
||||
#endif
|
||||
|
||||
#if LIBCURL_VERSION_NUM < 0x070c03
|
||||
#define NO_CURL_IOCTL
|
||||
#endif
|
||||
|
||||
struct slot_results
|
||||
{
|
||||
CURLcode curl_result;
|
||||
@@ -67,6 +71,9 @@ struct buffer
|
||||
extern size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
||||
extern size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
||||
extern size_t fwrite_null(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
|
||||
#ifndef NO_CURL_IOCTL
|
||||
extern curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
|
||||
#endif
|
||||
|
||||
/* Slot lifecycle functions */
|
||||
extern struct active_request_slot *get_active_slot(void);
|
||||
|
||||
@@ -823,8 +823,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
|
||||
}
|
||||
if (move_temp_to_file(curr_pack_name, final_pack_name))
|
||||
die("cannot store pack file");
|
||||
}
|
||||
if (from_stdin)
|
||||
} else if (from_stdin)
|
||||
chmod(final_pack_name, 0444);
|
||||
|
||||
if (final_index_name != curr_index_name) {
|
||||
@@ -835,8 +834,8 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
|
||||
}
|
||||
if (move_temp_to_file(curr_index_name, final_index_name))
|
||||
die("cannot store index file");
|
||||
}
|
||||
chmod(final_index_name, 0444);
|
||||
} else
|
||||
chmod(final_index_name, 0444);
|
||||
|
||||
if (!from_stdin) {
|
||||
printf("%s\n", sha1_to_hex(sha1));
|
||||
|
||||
@@ -23,7 +23,6 @@ static void process_blob(struct rev_info *revs,
|
||||
if (obj->flags & (UNINTERESTING | SEEN))
|
||||
return;
|
||||
obj->flags |= SEEN;
|
||||
name = xstrdup(name);
|
||||
add_object(obj, p, path, name);
|
||||
}
|
||||
|
||||
@@ -78,7 +77,6 @@ static void process_tree(struct rev_info *revs,
|
||||
if (parse_tree(tree) < 0)
|
||||
die("bad tree object %s", sha1_to_hex(obj->sha1));
|
||||
obj->flags |= SEEN;
|
||||
name = xstrdup(name);
|
||||
add_object(obj, p, path, name);
|
||||
me.up = path;
|
||||
me.elem = name;
|
||||
|
||||
35
log-tree.c
35
log-tree.c
@@ -179,13 +179,31 @@ static int has_non_ascii(const char *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void log_write_email_headers(struct rev_info *opt, const char *name,
|
||||
void get_patch_filename(struct commit *commit, int nr, const char *suffix,
|
||||
struct strbuf *buf)
|
||||
{
|
||||
int suffix_len = strlen(suffix) + 1;
|
||||
int start_len = buf->len;
|
||||
|
||||
strbuf_addf(buf, commit ? "%04d-" : "%d", nr);
|
||||
if (commit) {
|
||||
int max_len = start_len + FORMAT_PATCH_NAME_MAX - suffix_len;
|
||||
|
||||
format_commit_message(commit, "%f", buf, DATE_NORMAL);
|
||||
if (max_len < buf->len)
|
||||
strbuf_setlen(buf, max_len);
|
||||
strbuf_addstr(buf, suffix);
|
||||
}
|
||||
}
|
||||
|
||||
void log_write_email_headers(struct rev_info *opt, struct commit *commit,
|
||||
const char **subject_p,
|
||||
const char **extra_headers_p,
|
||||
int *need_8bit_cte_p)
|
||||
{
|
||||
const char *subject = NULL;
|
||||
const char *extra_headers = opt->extra_headers;
|
||||
const char *name = sha1_to_hex(commit->object.sha1);
|
||||
|
||||
*need_8bit_cte_p = 0; /* unknown */
|
||||
if (opt->total > 0) {
|
||||
@@ -224,6 +242,7 @@ void log_write_email_headers(struct rev_info *opt, const char *name,
|
||||
if (opt->mime_boundary) {
|
||||
static char subject_buffer[1024];
|
||||
static char buffer[1024];
|
||||
struct strbuf filename = STRBUF_INIT;
|
||||
*need_8bit_cte_p = -1; /* NEVER */
|
||||
snprintf(subject_buffer, sizeof(subject_buffer) - 1,
|
||||
"%s"
|
||||
@@ -242,18 +261,21 @@ void log_write_email_headers(struct rev_info *opt, const char *name,
|
||||
mime_boundary_leader, opt->mime_boundary);
|
||||
extra_headers = subject_buffer;
|
||||
|
||||
get_patch_filename(opt->numbered_files ? NULL : commit, opt->nr,
|
||||
opt->patch_suffix, &filename);
|
||||
snprintf(buffer, sizeof(buffer) - 1,
|
||||
"\n--%s%s\n"
|
||||
"Content-Type: text/x-patch;"
|
||||
" name=\"%s.diff\"\n"
|
||||
" name=\"%s\"\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Content-Disposition: %s;"
|
||||
" filename=\"%s.diff\"\n\n",
|
||||
" filename=\"%s\"\n\n",
|
||||
mime_boundary_leader, opt->mime_boundary,
|
||||
name,
|
||||
filename.buf,
|
||||
opt->no_inline ? "attachment" : "inline",
|
||||
name);
|
||||
filename.buf);
|
||||
opt->diffopt.stat_sep = buffer;
|
||||
strbuf_release(&filename);
|
||||
}
|
||||
*subject_p = subject;
|
||||
*extra_headers_p = extra_headers;
|
||||
@@ -333,8 +355,7 @@ void show_log(struct rev_info *opt)
|
||||
*/
|
||||
|
||||
if (opt->commit_format == CMIT_FMT_EMAIL) {
|
||||
log_write_email_headers(opt, sha1_to_hex(commit->object.sha1),
|
||||
&subject, &extra_headers,
|
||||
log_write_email_headers(opt, commit, &subject, &extra_headers,
|
||||
&need_8bit_cte);
|
||||
} else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
|
||||
fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), stdout);
|
||||
|
||||
@@ -13,10 +13,14 @@ int log_tree_commit(struct rev_info *, struct commit *);
|
||||
int log_tree_opt_parse(struct rev_info *, const char **, int);
|
||||
void show_log(struct rev_info *opt);
|
||||
void show_decorations(struct rev_info *opt, struct commit *commit);
|
||||
void log_write_email_headers(struct rev_info *opt, const char *name,
|
||||
void log_write_email_headers(struct rev_info *opt, struct commit *commit,
|
||||
const char **subject_p,
|
||||
const char **extra_headers_p,
|
||||
int *need_8bit_cte_p);
|
||||
void load_ref_decorations(void);
|
||||
|
||||
#define FORMAT_PATCH_NAME_MAX 64
|
||||
void get_patch_filename(struct commit *commit, int nr, const char *suffix,
|
||||
struct strbuf *buf);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1116,21 +1116,13 @@ static int process_entry(struct merge_options *o,
|
||||
o->branch1, o->branch2);
|
||||
|
||||
clean_merge = mfi.clean;
|
||||
if (mfi.clean)
|
||||
update_file(o, 1, mfi.sha, mfi.mode, path);
|
||||
else if (S_ISGITLINK(mfi.mode))
|
||||
output(o, 1, "CONFLICT (submodule): Merge conflict in %s "
|
||||
"- needs %s", path, sha1_to_hex(b.sha1));
|
||||
else {
|
||||
if (!mfi.clean) {
|
||||
if (S_ISGITLINK(mfi.mode))
|
||||
reason = "submodule";
|
||||
output(o, 1, "CONFLICT (%s): Merge conflict in %s",
|
||||
reason, path);
|
||||
|
||||
if (o->call_depth)
|
||||
update_file(o, 0, mfi.sha, mfi.mode, path);
|
||||
else
|
||||
update_file_flags(o, mfi.sha, mfi.mode, path,
|
||||
0 /* update_cache */, 1 /* update_working_directory */);
|
||||
}
|
||||
update_file(o, mfi.clean, mfi.sha, mfi.mode, path);
|
||||
} else if (!o_sha && !a_sha && !b_sha) {
|
||||
/*
|
||||
* this entry was deleted altogether. a_mode == 0 means
|
||||
|
||||
53
path.c
53
path.c
@@ -311,36 +311,49 @@ char *enter_repo(char *path, int strict)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int adjust_shared_perm(const char *path)
|
||||
int set_shared_perm(const char *path, int mode)
|
||||
{
|
||||
struct stat st;
|
||||
int mode;
|
||||
int tweak, shared, orig_mode;
|
||||
|
||||
if (!shared_repository)
|
||||
if (!shared_repository) {
|
||||
if (mode)
|
||||
return chmod(path, mode & ~S_IFMT);
|
||||
return 0;
|
||||
if (lstat(path, &st) < 0)
|
||||
return -1;
|
||||
mode = st.st_mode;
|
||||
|
||||
if (shared_repository) {
|
||||
int tweak = shared_repository;
|
||||
if (!(mode & S_IWUSR))
|
||||
tweak &= ~0222;
|
||||
mode |= tweak;
|
||||
} else {
|
||||
/* Preserve old PERM_UMASK behaviour */
|
||||
if (mode & S_IWUSR)
|
||||
mode |= S_IWGRP;
|
||||
}
|
||||
if (!mode) {
|
||||
if (lstat(path, &st) < 0)
|
||||
return -1;
|
||||
mode = st.st_mode;
|
||||
orig_mode = mode;
|
||||
} else
|
||||
orig_mode = 0;
|
||||
if (shared_repository < 0)
|
||||
shared = -shared_repository;
|
||||
else
|
||||
shared = shared_repository;
|
||||
tweak = shared;
|
||||
|
||||
if (!(mode & S_IWUSR))
|
||||
tweak &= ~0222;
|
||||
if (mode & S_IXUSR)
|
||||
/* Copy read bits to execute bits */
|
||||
tweak |= (tweak & 0444) >> 2;
|
||||
if (shared_repository < 0)
|
||||
mode = (mode & ~0777) | tweak;
|
||||
else
|
||||
mode |= tweak;
|
||||
|
||||
if (S_ISDIR(mode)) {
|
||||
mode |= FORCE_DIR_SET_GID;
|
||||
|
||||
/* Copy read bits to execute bits */
|
||||
mode |= (shared_repository & 0444) >> 2;
|
||||
mode |= (shared & 0444) >> 2;
|
||||
mode |= FORCE_DIR_SET_GID;
|
||||
}
|
||||
|
||||
if ((mode & st.st_mode) != mode && chmod(path, mode) < 0)
|
||||
if (((shared_repository < 0
|
||||
? (orig_mode & (FORCE_DIR_SET_GID | 0777))
|
||||
: (orig_mode & mode)) != mode) &&
|
||||
chmod(path, (mode & ~S_IFMT)) < 0)
|
||||
return -2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
12
perl/Git.pm
12
perl/Git.pm
@@ -56,7 +56,7 @@ require Exporter;
|
||||
@EXPORT_OK = qw(command command_oneline command_noisy
|
||||
command_output_pipe command_input_pipe command_close_pipe
|
||||
command_bidi_pipe command_close_bidi_pipe
|
||||
version exec_path hash_object git_cmd_try
|
||||
version exec_path html_path hash_object git_cmd_try
|
||||
remote_refs
|
||||
temp_acquire temp_release temp_reset temp_path);
|
||||
|
||||
@@ -492,6 +492,16 @@ C<git --exec-path>). Useful mostly only internally.
|
||||
sub exec_path { command_oneline('--exec-path') }
|
||||
|
||||
|
||||
=item html_path ()
|
||||
|
||||
Return path to the Git html documentation (the same as
|
||||
C<git --html-path>). Useful mostly only internally.
|
||||
|
||||
=cut
|
||||
|
||||
sub html_path { command_oneline('--html-path') }
|
||||
|
||||
|
||||
=item repo_path ()
|
||||
|
||||
Return path to the git repository. Must be called on a repository instance.
|
||||
|
||||
37
pretty.c
37
pretty.c
@@ -493,6 +493,40 @@ static void parse_commit_header(struct format_commit_context *context)
|
||||
context->commit_header_parsed = 1;
|
||||
}
|
||||
|
||||
static int istitlechar(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') || c == '.' || c == '_';
|
||||
}
|
||||
|
||||
static void format_sanitized_subject(struct strbuf *sb, const char *msg)
|
||||
{
|
||||
size_t trimlen;
|
||||
size_t start_len = sb->len;
|
||||
int space = 2;
|
||||
|
||||
for (; *msg && *msg != '\n'; msg++) {
|
||||
if (istitlechar(*msg)) {
|
||||
if (space == 1)
|
||||
strbuf_addch(sb, '-');
|
||||
space = 0;
|
||||
strbuf_addch(sb, *msg);
|
||||
if (*msg == '.')
|
||||
while (*(msg+1) == '.')
|
||||
msg++;
|
||||
} else
|
||||
space |= 1;
|
||||
}
|
||||
|
||||
/* trim any trailing '.' or '-' characters */
|
||||
trimlen = 0;
|
||||
while (sb->len - trimlen > start_len &&
|
||||
(sb->buf[sb->len - 1 - trimlen] == '.'
|
||||
|| sb->buf[sb->len - 1 - trimlen] == '-'))
|
||||
trimlen++;
|
||||
strbuf_remove(sb, sb->len - trimlen, trimlen);
|
||||
}
|
||||
|
||||
const char *format_subject(struct strbuf *sb, const char *msg,
|
||||
const char *line_separator)
|
||||
{
|
||||
@@ -683,6 +717,9 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
|
||||
case 's': /* subject */
|
||||
format_subject(sb, msg + c->subject_off, " ");
|
||||
return 1;
|
||||
case 'f': /* sanitized subject */
|
||||
format_sanitized_subject(sb, msg + c->subject_off);
|
||||
return 1;
|
||||
case 'b': /* body */
|
||||
strbuf_addstr(sb, msg + c->body_off);
|
||||
return 1;
|
||||
|
||||
@@ -48,7 +48,6 @@ static void process_tree(struct tree *tree,
|
||||
obj->flags |= SEEN;
|
||||
if (parse_tree(tree) < 0)
|
||||
die("bad tree object %s", sha1_to_hex(obj->sha1));
|
||||
name = xstrdup(name);
|
||||
add_object(obj, p, path, name);
|
||||
me.up = path;
|
||||
me.elem = name;
|
||||
|
||||
16
refs.c
16
refs.c
@@ -676,6 +676,7 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
|
||||
* - it has double dots "..", or
|
||||
* - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
|
||||
* - it ends with a "/".
|
||||
* - it ends with ".lock"
|
||||
*/
|
||||
|
||||
static inline int bad_ref_char(int ch)
|
||||
@@ -693,7 +694,7 @@ static inline int bad_ref_char(int ch)
|
||||
|
||||
int check_ref_format(const char *ref)
|
||||
{
|
||||
int ch, level, bad_type;
|
||||
int ch, level, bad_type, last;
|
||||
int ret = CHECK_REF_FORMAT_OK;
|
||||
const char *cp = ref;
|
||||
|
||||
@@ -717,21 +718,28 @@ int check_ref_format(const char *ref)
|
||||
return CHECK_REF_FORMAT_ERROR;
|
||||
}
|
||||
|
||||
last = ch;
|
||||
/* scan the rest of the path component */
|
||||
while ((ch = *cp++) != 0) {
|
||||
bad_type = bad_ref_char(ch);
|
||||
if (bad_type) {
|
||||
if (bad_type)
|
||||
return CHECK_REF_FORMAT_ERROR;
|
||||
}
|
||||
if (ch == '/')
|
||||
break;
|
||||
if (ch == '.' && *cp == '.')
|
||||
if (last == '.' && ch == '.')
|
||||
return CHECK_REF_FORMAT_ERROR;
|
||||
if (last == '@' && ch == '{')
|
||||
return CHECK_REF_FORMAT_ERROR;
|
||||
last = ch;
|
||||
}
|
||||
level++;
|
||||
if (!ch) {
|
||||
if (ref <= cp - 2 && cp[-2] == '.')
|
||||
return CHECK_REF_FORMAT_ERROR;
|
||||
if (level < 2)
|
||||
return CHECK_REF_FORMAT_ONELEVEL;
|
||||
if (has_extension(ref, ".lock"))
|
||||
return CHECK_REF_FORMAT_ERROR;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
7
remote.c
7
remote.c
@@ -1170,8 +1170,9 @@ struct branch *branch_get(const char *name)
|
||||
for (i = 0; i < ret->merge_nr; i++) {
|
||||
ret->merge[i] = xcalloc(1, sizeof(**ret->merge));
|
||||
ret->merge[i]->src = xstrdup(ret->merge_name[i]);
|
||||
remote_find_tracking(ret->remote,
|
||||
ret->merge[i]);
|
||||
if (remote_find_tracking(ret->remote, ret->merge[i])
|
||||
&& !strcmp(ret->remote_name, "."))
|
||||
ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1451,6 +1452,8 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb)
|
||||
base = branch->merge[0]->dst;
|
||||
if (!prefixcmp(base, "refs/remotes/")) {
|
||||
base += strlen("refs/remotes/");
|
||||
} else if (!prefixcmp(base, "refs/heads/")) {
|
||||
base += strlen("refs/heads/");
|
||||
}
|
||||
if (!num_theirs)
|
||||
strbuf_addf(sb, "Your branch is ahead of '%s' "
|
||||
|
||||
@@ -85,6 +85,8 @@ struct rev_info {
|
||||
struct log_info *loginfo;
|
||||
int nr, total;
|
||||
const char *mime_boundary;
|
||||
const char *patch_suffix;
|
||||
int numbered_files;
|
||||
char *message_id;
|
||||
struct string_list *ref_message_ids;
|
||||
const char *add_signoff;
|
||||
|
||||
4
setup.c
4
setup.c
@@ -434,7 +434,7 @@ int git_config_perm(const char *var, const char *value)
|
||||
|
||||
/*
|
||||
* Treat values 0, 1 and 2 as compatibility cases, otherwise it is
|
||||
* a chmod value.
|
||||
* a chmod value to restrict to.
|
||||
*/
|
||||
switch (i) {
|
||||
case PERM_UMASK: /* 0 */
|
||||
@@ -456,7 +456,7 @@ int git_config_perm(const char *var, const char *value)
|
||||
* Mask filemode value. Others can not get write permission.
|
||||
* x flags for directories are handled separately.
|
||||
*/
|
||||
return i & 0666;
|
||||
return -(i & 0666);
|
||||
}
|
||||
|
||||
int check_repository_format_version(const char *var, const char *value, void *cb)
|
||||
|
||||
14
sha1_file.c
14
sha1_file.c
@@ -2216,11 +2216,15 @@ static void write_sha1_file_prepare(const void *buf, unsigned long len,
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the just written object into its final resting place
|
||||
* Move the just written object into its final resting place.
|
||||
* NEEDSWORK: this should be renamed to finalize_temp_file() as
|
||||
* "moving" is only a part of what it does, when no patch between
|
||||
* master to pu changes the call sites of this function.
|
||||
*/
|
||||
int move_temp_to_file(const char *tmpfile, const char *filename)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (link(tmpfile, filename))
|
||||
ret = errno;
|
||||
|
||||
@@ -2232,12 +2236,12 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
|
||||
*
|
||||
* The same holds for FAT formatted media.
|
||||
*
|
||||
* When this succeeds, we just return 0. We have nothing
|
||||
* When this succeeds, we just return. We have nothing
|
||||
* left to unlink.
|
||||
*/
|
||||
if (ret && ret != EEXIST) {
|
||||
if (!rename(tmpfile, filename))
|
||||
return 0;
|
||||
goto out;
|
||||
ret = errno;
|
||||
}
|
||||
unlink(tmpfile);
|
||||
@@ -2248,6 +2252,9 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
|
||||
/* FIXME!!! Collision check here ? */
|
||||
}
|
||||
|
||||
out:
|
||||
if (set_shared_perm(filename, (S_IFREG|0444)))
|
||||
return error("unable to set permission to '%s'", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2272,7 +2279,6 @@ static void close_sha1_file(int fd)
|
||||
{
|
||||
if (fsync_object_files)
|
||||
fsync_or_die(fd, "sha1 file");
|
||||
fchmod(fd, 0444);
|
||||
if (close(fd) != 0)
|
||||
die("error when closing sha1 file (%s)", strerror(errno));
|
||||
}
|
||||
|
||||
12
sha1_name.c
12
sha1_name.c
@@ -242,10 +242,10 @@ static int ambiguous_path(const char *path, int len)
|
||||
* *string and *len will only be substituted, and *string returned (for
|
||||
* later free()ing) if the string passed in is of the form @{-<n>}.
|
||||
*/
|
||||
static char *substitute_nth_last_branch(const char **string, int *len)
|
||||
static char *substitute_branch_name(const char **string, int *len)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int ret = interpret_nth_last_branch(*string, &buf);
|
||||
int ret = interpret_branch_name(*string, &buf);
|
||||
|
||||
if (ret == *len) {
|
||||
size_t size;
|
||||
@@ -259,7 +259,7 @@ static char *substitute_nth_last_branch(const char **string, int *len)
|
||||
|
||||
int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
|
||||
{
|
||||
char *last_branch = substitute_nth_last_branch(&str, &len);
|
||||
char *last_branch = substitute_branch_name(&str, &len);
|
||||
const char **p, *r;
|
||||
int refs_found = 0;
|
||||
|
||||
@@ -288,7 +288,7 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
|
||||
|
||||
int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
|
||||
{
|
||||
char *last_branch = substitute_nth_last_branch(&str, &len);
|
||||
char *last_branch = substitute_branch_name(&str, &len);
|
||||
const char **p;
|
||||
int logs_found = 0;
|
||||
|
||||
@@ -355,7 +355,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int ret;
|
||||
/* try the @{-N} syntax for n-th checkout */
|
||||
ret = interpret_nth_last_branch(str+at, &buf);
|
||||
ret = interpret_branch_name(str+at, &buf);
|
||||
if (ret > 0) {
|
||||
/* substitute this branch name and restart */
|
||||
return get_sha1_1(buf.buf, buf.len, sha1);
|
||||
@@ -750,7 +750,7 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
|
||||
* If the input was ok but there are not N branch switches in the
|
||||
* reflog, it returns 0.
|
||||
*/
|
||||
int interpret_nth_last_branch(const char *name, struct strbuf *buf)
|
||||
int interpret_branch_name(const char *name, struct strbuf *buf)
|
||||
{
|
||||
long nth;
|
||||
int i, retval;
|
||||
|
||||
17
strbuf.c
17
strbuf.c
@@ -1,4 +1,5 @@
|
||||
#include "cache.h"
|
||||
#include "refs.h"
|
||||
|
||||
int prefixcmp(const char *str, const char *prefix)
|
||||
{
|
||||
@@ -357,3 +358,19 @@ int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int strbuf_branchname(struct strbuf *sb, const char *name)
|
||||
{
|
||||
int len = strlen(name);
|
||||
if (interpret_branch_name(name, sb) == len)
|
||||
return 0;
|
||||
strbuf_add(sb, name, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
|
||||
{
|
||||
strbuf_branchname(sb, name);
|
||||
strbuf_splice(sb, 0, 0, "refs/heads/", 11);
|
||||
return check_ref_format(sb->buf);
|
||||
}
|
||||
|
||||
3
strbuf.h
3
strbuf.h
@@ -131,4 +131,7 @@ extern int strbuf_getline(struct strbuf *, FILE *, int);
|
||||
extern void stripspace(struct strbuf *buf, int skip_comments);
|
||||
extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);
|
||||
|
||||
extern int strbuf_branchname(struct strbuf *sb, const char *name);
|
||||
extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);
|
||||
|
||||
#endif /* STRBUF_H */
|
||||
|
||||
@@ -7,7 +7,6 @@ if test -n "$NO_SVN_TESTS"
|
||||
then
|
||||
say 'skipping git svn tests, NO_SVN_TESTS defined'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
GIT_DIR=$PWD/.git
|
||||
@@ -19,7 +18,6 @@ if test $? -ne 1
|
||||
then
|
||||
say 'skipping git svn tests, svn not found'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
svnrepo=$PWD/svnrepo
|
||||
@@ -43,7 +41,6 @@ then
|
||||
fi
|
||||
say "$err"
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
rawsvnrepo="$svnrepo"
|
||||
@@ -144,7 +141,6 @@ require_svnserve () {
|
||||
then
|
||||
say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ then
|
||||
say "skipping test, network testing disabled by default"
|
||||
say "(define GIT_TEST_HTTPD to enable)"
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
HTTPD_PARA=""
|
||||
@@ -36,7 +35,6 @@ if ! test -x "$LIB_HTTPD_PATH"
|
||||
then
|
||||
say "skipping test, no web server found at '$LIB_HTTPD_PATH'"
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
HTTPD_VERSION=`$LIB_HTTPD_PATH -v | \
|
||||
@@ -50,7 +48,6 @@ then
|
||||
then
|
||||
say "skipping test, at least Apache version 2 is required"
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
LIB_HTTPD_MODULE_PATH="$DEFAULT_HTTPD_MODULE_PATH"
|
||||
|
||||
@@ -126,4 +126,41 @@ test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' '
|
||||
esac
|
||||
'
|
||||
|
||||
test_expect_success 'forced modes' '
|
||||
mkdir -p templates/hooks &&
|
||||
echo update-server-info >templates/hooks/post-update &&
|
||||
chmod +x templates/hooks/post-update &&
|
||||
echo : >random-file &&
|
||||
mkdir new &&
|
||||
(
|
||||
cd new &&
|
||||
umask 002 &&
|
||||
git init --shared=0660 --template=../templates &&
|
||||
>frotz &&
|
||||
git add frotz &&
|
||||
git commit -a -m initial &&
|
||||
git repack
|
||||
) &&
|
||||
find new/.git -print |
|
||||
xargs ls -ld >actual &&
|
||||
|
||||
# Everything must be unaccessible to others
|
||||
test -z "$(sed -n -e "/^.......---/d" actual)" &&
|
||||
|
||||
# All directories must have either 2770 or 770
|
||||
test -z "$(sed -n -e "/^drwxrw[sx]---/d" -e "/^d/p" actual)" &&
|
||||
|
||||
# post-update hook must be 0770
|
||||
test -z "$(sed -n -e "/post-update/{
|
||||
/^-rwxrwx---/d
|
||||
p
|
||||
}" actual)" &&
|
||||
|
||||
# All files inside objects must be 0440
|
||||
test -z "$(sed -n -e "/objects\//{
|
||||
/^d/d
|
||||
/^-r--r-----/d
|
||||
}" actual)"
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
42
t/t2013-checkout-submodule.sh
Executable file
42
t/t2013-checkout-submodule.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='checkout can handle submodules'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup' '
|
||||
mkdir submodule &&
|
||||
(cd submodule &&
|
||||
git init &&
|
||||
test_commit first) &&
|
||||
git add submodule &&
|
||||
test_tick &&
|
||||
git commit -m superproject &&
|
||||
(cd submodule &&
|
||||
test_commit second) &&
|
||||
git add submodule &&
|
||||
test_tick &&
|
||||
git commit -m updated.superproject
|
||||
'
|
||||
|
||||
test_expect_success '"reset <submodule>" updates the index' '
|
||||
git update-index --refresh &&
|
||||
git diff-files --quiet &&
|
||||
git diff-index --quiet --cached HEAD &&
|
||||
test_must_fail git reset HEAD^ submodule &&
|
||||
test_must_fail git diff-files --quiet &&
|
||||
git reset submodule &&
|
||||
git diff-files --quiet
|
||||
'
|
||||
|
||||
test_expect_success '"checkout <submodule>" updates the index only' '
|
||||
git update-index --refresh &&
|
||||
git diff-files --quiet &&
|
||||
git diff-index --quiet --cached HEAD &&
|
||||
git checkout HEAD^ submodule &&
|
||||
test_must_fail git diff-files --quiet &&
|
||||
git checkout HEAD submodule &&
|
||||
git diff-files --quiet
|
||||
'
|
||||
|
||||
test_done
|
||||
@@ -135,4 +135,10 @@ test_expect_success \
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
test_expect_success 'ls-tree filter is leading path match' '
|
||||
git ls-tree $tree pa path3/a >current &&
|
||||
>expected &&
|
||||
test_output
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -16,7 +16,6 @@ if ! test_have_prereq SYMLINKS
|
||||
then
|
||||
say 'Symbolic links not supported, skipping tests.'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
test_expect_success \
|
||||
|
||||
@@ -62,4 +62,12 @@ test_expect_success \
|
||||
'git diff-index --cached $tree -- file0/ >current &&
|
||||
compare_diff_raw current expected'
|
||||
|
||||
test_expect_success 'diff-tree pathspec' '
|
||||
tree2=$(git write-tree) &&
|
||||
echo "$tree2" &&
|
||||
git diff-tree -r --name-only $tree $tree2 -- pa path1/a >current &&
|
||||
>expected &&
|
||||
test_cmp expected current
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -13,7 +13,6 @@ if ! test_have_prereq SYMLINKS
|
||||
then
|
||||
say 'Symbolic links not supported, skipping tests.'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
cat > expected << EOF
|
||||
|
||||
@@ -246,11 +246,12 @@ format-patch --stdout initial..master
|
||||
format-patch --stdout --no-numbered initial..master
|
||||
format-patch --stdout --numbered initial..master
|
||||
format-patch --attach --stdout initial..side
|
||||
format-patch --attach --stdout --suffix=.diff initial..side
|
||||
format-patch --attach --stdout initial..master^
|
||||
format-patch --attach --stdout initial..master
|
||||
format-patch --inline --stdout initial..side
|
||||
format-patch --inline --stdout initial..master^
|
||||
format-patch --inline --stdout initial..master
|
||||
format-patch --inline --stdout --numbered-files initial..master
|
||||
format-patch --inline --stdout initial..master
|
||||
format-patch --inline --stdout --subject-prefix=TESTCASE initial..master
|
||||
config format.subjectprefix DIFFERENT_PREFIX
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
$ git format-patch --attach --stdout --suffix=.diff initial..side
|
||||
From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
|
||||
From: A U Thor <author@example.com>
|
||||
Date: Mon, 26 Jun 2006 00:03:00 +0000
|
||||
Subject: [PATCH] Side
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/plain; charset=UTF-8; format=fixed
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
---
|
||||
dir/sub | 2 ++
|
||||
file0 | 3 +++
|
||||
file3 | 4 ++++
|
||||
3 files changed, 9 insertions(+), 0 deletions(-)
|
||||
create mode 100644 file3
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="0001-Side.diff"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: attachment; filename="0001-Side.diff"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..7289e35 100644
|
||||
--- a/dir/sub
|
||||
+++ b/dir/sub
|
||||
@@ -1,2 +1,4 @@
|
||||
A
|
||||
B
|
||||
+1
|
||||
+2
|
||||
diff --git a/file0 b/file0
|
||||
index 01e79c3..f4615da 100644
|
||||
--- a/file0
|
||||
+++ b/file0
|
||||
@@ -1,3 +1,6 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
+A
|
||||
+B
|
||||
+C
|
||||
diff --git a/file3 b/file3
|
||||
new file mode 100644
|
||||
index 0000000..7289e35
|
||||
--- /dev/null
|
||||
+++ b/file3
|
||||
@@ -0,0 +1,4 @@
|
||||
+A
|
||||
+B
|
||||
+1
|
||||
+2
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n--
|
||||
|
||||
|
||||
$
|
||||
@@ -22,9 +22,9 @@ This is the second commit.
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Type: text/x-patch; name="0001-Second.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: attachment; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Disposition: attachment; filename="0001-Second.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..8422d40 100644
|
||||
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Type: text/x-patch; name="0002-Third.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: attachment; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Disposition: attachment; filename="0002-Third.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 8422d40..cead32e 100644
|
||||
@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Type: text/x-patch; name="0003-Side.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: attachment; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Disposition: attachment; filename="0003-Side.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..7289e35 100644
|
||||
|
||||
@@ -22,9 +22,9 @@ This is the second commit.
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Type: text/x-patch; name="0001-Second.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: attachment; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Disposition: attachment; filename="0001-Second.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..8422d40 100644
|
||||
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Type: text/x-patch; name="0002-Third.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: attachment; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Disposition: attachment; filename="0002-Third.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 8422d40..cead32e 100644
|
||||
|
||||
@@ -20,9 +20,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Type: text/x-patch; name="0001-Side.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: attachment; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Disposition: attachment; filename="0001-Side.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..7289e35 100644
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
$ git format-patch --inline --stdout --numbered-files initial..master
|
||||
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
|
||||
From: A U Thor <author@example.com>
|
||||
Date: Mon, 26 Jun 2006 00:01:00 +0000
|
||||
Subject: [PATCH 1/3] Second
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/plain; charset=UTF-8; format=fixed
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
This is the second commit.
|
||||
---
|
||||
dir/sub | 2 ++
|
||||
file0 | 3 +++
|
||||
file2 | 3 ---
|
||||
3 files changed, 5 insertions(+), 3 deletions(-)
|
||||
delete mode 100644 file2
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="1"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="1"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..8422d40 100644
|
||||
--- a/dir/sub
|
||||
+++ b/dir/sub
|
||||
@@ -1,2 +1,4 @@
|
||||
A
|
||||
B
|
||||
+C
|
||||
+D
|
||||
diff --git a/file0 b/file0
|
||||
index 01e79c3..b414108 100644
|
||||
--- a/file0
|
||||
+++ b/file0
|
||||
@@ -1,3 +1,6 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
+4
|
||||
+5
|
||||
+6
|
||||
diff --git a/file2 b/file2
|
||||
deleted file mode 100644
|
||||
index 01e79c3..0000000
|
||||
--- a/file2
|
||||
+++ /dev/null
|
||||
@@ -1,3 +0,0 @@
|
||||
-1
|
||||
-2
|
||||
-3
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n--
|
||||
|
||||
|
||||
|
||||
From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
|
||||
From: A U Thor <author@example.com>
|
||||
Date: Mon, 26 Jun 2006 00:02:00 +0000
|
||||
Subject: [PATCH 2/3] Third
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/plain; charset=UTF-8; format=fixed
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
---
|
||||
dir/sub | 2 ++
|
||||
file1 | 3 +++
|
||||
2 files changed, 5 insertions(+), 0 deletions(-)
|
||||
create mode 100644 file1
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="2"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="2"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 8422d40..cead32e 100644
|
||||
--- a/dir/sub
|
||||
+++ b/dir/sub
|
||||
@@ -2,3 +2,5 @@ A
|
||||
B
|
||||
C
|
||||
D
|
||||
+E
|
||||
+F
|
||||
diff --git a/file1 b/file1
|
||||
new file mode 100644
|
||||
index 0000000..b1e6722
|
||||
--- /dev/null
|
||||
+++ b/file1
|
||||
@@ -0,0 +1,3 @@
|
||||
+A
|
||||
+B
|
||||
+C
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n--
|
||||
|
||||
|
||||
|
||||
From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
|
||||
From: A U Thor <author@example.com>
|
||||
Date: Mon, 26 Jun 2006 00:03:00 +0000
|
||||
Subject: [PATCH 3/3] Side
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/plain; charset=UTF-8; format=fixed
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
---
|
||||
dir/sub | 2 ++
|
||||
file0 | 3 +++
|
||||
file3 | 4 ++++
|
||||
3 files changed, 9 insertions(+), 0 deletions(-)
|
||||
create mode 100644 file3
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="3"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="3"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..7289e35 100644
|
||||
--- a/dir/sub
|
||||
+++ b/dir/sub
|
||||
@@ -1,2 +1,4 @@
|
||||
A
|
||||
B
|
||||
+1
|
||||
+2
|
||||
diff --git a/file0 b/file0
|
||||
index 01e79c3..f4615da 100644
|
||||
--- a/file0
|
||||
+++ b/file0
|
||||
@@ -1,3 +1,6 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
+A
|
||||
+B
|
||||
+C
|
||||
diff --git a/file3 b/file3
|
||||
new file mode 100644
|
||||
index 0000000..7289e35
|
||||
--- /dev/null
|
||||
+++ b/file3
|
||||
@@ -0,0 +1,4 @@
|
||||
+A
|
||||
+B
|
||||
+1
|
||||
+2
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n--
|
||||
|
||||
|
||||
$
|
||||
@@ -22,9 +22,9 @@ This is the second commit.
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Type: text/x-patch; name="0001-Second.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Disposition: inline; filename="0001-Second.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..8422d40 100644
|
||||
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Type: text/x-patch; name="0002-Third.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Disposition: inline; filename="0002-Third.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 8422d40..cead32e 100644
|
||||
@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Type: text/x-patch; name="0003-Side.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Disposition: inline; filename="0003-Side.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..7289e35 100644
|
||||
|
||||
@@ -22,9 +22,9 @@ This is the second commit.
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Type: text/x-patch; name="0001-Second.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Disposition: inline; filename="0001-Second.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..8422d40 100644
|
||||
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Type: text/x-patch; name="0002-Third.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Disposition: inline; filename="0002-Third.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 8422d40..cead32e 100644
|
||||
@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Type: text/x-patch; name="0003-Side.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Disposition: inline; filename="0003-Side.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..7289e35 100644
|
||||
|
||||
@@ -22,9 +22,9 @@ This is the second commit.
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Type: text/x-patch; name="0001-Second.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Disposition: inline; filename="0001-Second.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..8422d40 100644
|
||||
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Type: text/x-patch; name="0002-Third.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
|
||||
Content-Disposition: inline; filename="0002-Third.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 8422d40..cead32e 100644
|
||||
|
||||
@@ -22,9 +22,9 @@ This is the second commit.
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Type: text/x-patch; name="0001-Second.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
|
||||
Content-Disposition: inline; filename="0001-Second.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..8422d40 100644
|
||||
|
||||
@@ -20,9 +20,9 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
--------------g-i-t--v-e-r-s-i-o-n
|
||||
Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Type: text/x-patch; name="0001-Side.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
|
||||
Content-Disposition: inline; filename="0001-Side.patch"
|
||||
|
||||
diff --git a/dir/sub b/dir/sub
|
||||
index 35d242b..7289e35 100644
|
||||
|
||||
@@ -8,7 +8,6 @@ if ! test_have_prereq SYMLINKS
|
||||
then
|
||||
say 'Symbolic links not supported, skipping tests.'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
test_expect_success setup '
|
||||
|
||||
@@ -13,7 +13,6 @@ if ! test_have_prereq SYMLINKS
|
||||
then
|
||||
say 'Symbolic links not supported, skipping tests.'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
test_expect_success 'setup repository and commits' '
|
||||
|
||||
@@ -13,7 +13,6 @@ if ! test_have_prereq SYMLINKS
|
||||
then
|
||||
say 'Symbolic links not supported, skipping tests.'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
test_expect_success setup '
|
||||
|
||||
@@ -7,7 +7,6 @@ if ! test_have_prereq SYMLINKS
|
||||
then
|
||||
say 'Symbolic links not supported, skipping tests.'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
lecho () {
|
||||
|
||||
@@ -8,7 +8,6 @@ case $(uname -s) in
|
||||
*MINGW*)
|
||||
say "GIT_DEBUG_SEND_PACK not supported - skipping tests"
|
||||
test_done
|
||||
exit
|
||||
esac
|
||||
|
||||
# End state of the repository:
|
||||
|
||||
@@ -8,7 +8,6 @@ if ! test_have_prereq SYMLINKS
|
||||
then
|
||||
say 'Symbolic links not supported, skipping tests.'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
# The scenario we are building:
|
||||
|
||||
@@ -17,7 +17,6 @@ if git http-push > /dev/null 2>&1 || [ $? -eq 128 ]
|
||||
then
|
||||
say "skipping test, USE_CURL_MULTI is not defined"
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
. "$TEST_DIRECTORY"/lib-httpd.sh
|
||||
|
||||
@@ -29,7 +29,9 @@ test_expect_success setup '
|
||||
git checkout -b b4 origin &&
|
||||
advance e &&
|
||||
advance f
|
||||
)
|
||||
) &&
|
||||
git checkout -b follower --track master &&
|
||||
advance g
|
||||
'
|
||||
|
||||
script='s/^..\(b.\)[ 0-9a-f]*\[\([^]]*\)\].*/\1 \2/p'
|
||||
@@ -56,6 +58,12 @@ test_expect_success 'checkout' '
|
||||
grep "have 1 and 1 different" actual
|
||||
'
|
||||
|
||||
test_expect_success 'checkout with local tracked branch' '
|
||||
git checkout master &&
|
||||
git checkout follower >actual
|
||||
grep "is ahead of" actual
|
||||
'
|
||||
|
||||
test_expect_success 'status' '
|
||||
(
|
||||
cd test &&
|
||||
|
||||
@@ -92,7 +92,6 @@ if ! echo 'echo space > "$1"' > "e space.sh"
|
||||
then
|
||||
say "Skipping; FS does not support spaces in filenames"
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
test_expect_success 'editor with a space' '
|
||||
|
||||
@@ -171,7 +171,7 @@ test_expect_success 'checkout to detach HEAD' '
|
||||
git checkout -f renamer && git clean -f &&
|
||||
git checkout renamer^ 2>messages &&
|
||||
(cat >messages.expect <<EOF
|
||||
Note: moving to "renamer^" which isn'"'"'t a local branch
|
||||
Note: moving to '\''renamer^'\'' which isn'\''t a local branch
|
||||
If you want to create a new branch from this checkout, you may do so
|
||||
(now or later) by using -b with the checkout command again. Example:
|
||||
git checkout -b <new_branch_name>
|
||||
|
||||
74
t/t7405-submodule-merge.sh
Executable file
74
t/t7405-submodule-merge.sh
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='merging with submodules'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
#
|
||||
# history
|
||||
#
|
||||
# a --- c
|
||||
# / \ /
|
||||
# root X
|
||||
# \ / \
|
||||
# b --- d
|
||||
#
|
||||
|
||||
test_expect_success setup '
|
||||
|
||||
mkdir sub &&
|
||||
(cd sub &&
|
||||
git init &&
|
||||
echo original > file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
git commit -m sub-root) &&
|
||||
git add sub &&
|
||||
test_tick &&
|
||||
git commit -m root &&
|
||||
|
||||
git checkout -b a master &&
|
||||
(cd sub &&
|
||||
echo A > file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
git commit -m sub-a) &&
|
||||
git add sub &&
|
||||
test_tick &&
|
||||
git commit -m a &&
|
||||
|
||||
git checkout -b b master &&
|
||||
(cd sub &&
|
||||
echo B > file &&
|
||||
git add file &&
|
||||
test_tick &&
|
||||
git commit -m sub-b) &&
|
||||
git add sub &&
|
||||
test_tick &&
|
||||
git commit -m b
|
||||
|
||||
git checkout -b c a &&
|
||||
git merge -s ours b &&
|
||||
|
||||
git checkout -b d b &&
|
||||
git merge -s ours a
|
||||
'
|
||||
|
||||
test_expect_failure 'merging with modify/modify conflict' '
|
||||
|
||||
git checkout -b test1 a &&
|
||||
test_must_fail git merge b &&
|
||||
test -f .git/MERGE_MSG &&
|
||||
git diff
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'merging with a modify/modify conflict between merge bases' '
|
||||
|
||||
git reset --hard HEAD &&
|
||||
git checkout -b test2 c &&
|
||||
git merge d
|
||||
|
||||
'
|
||||
|
||||
test_done
|
||||
@@ -130,6 +130,19 @@ test_expect_success 'Show all headers' '
|
||||
test_cmp expected-show-all-headers actual-show-all-headers
|
||||
'
|
||||
|
||||
test_expect_success 'Prompting works' '
|
||||
clean_fake_sendmail &&
|
||||
(echo "Example <from@example.com>"
|
||||
echo "to@example.com"
|
||||
echo ""
|
||||
) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
|
||||
--smtp-server="$(pwd)/fake.sendmail" \
|
||||
$patches \
|
||||
2>errors &&
|
||||
grep "^From: Example <from@example.com>$" msgtxt1 &&
|
||||
grep "^To: to@example.com$" msgtxt1
|
||||
'
|
||||
|
||||
z8=zzzzzzzz
|
||||
z64=$z8$z8$z8$z8$z8$z8$z8$z8
|
||||
z512=$z64$z64$z64$z64$z64$z64$z64$z64
|
||||
|
||||
@@ -11,7 +11,6 @@ if test $? -ne 1
|
||||
then
|
||||
say 'skipping git cvsexportcommit tests, cvs not found'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
CVSROOT=$(pwd)/cvsroot
|
||||
|
||||
@@ -15,12 +15,10 @@ if test $? -ne 1
|
||||
then
|
||||
say 'skipping git-cvsserver tests, cvs not found'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
|
||||
say 'skipping git-cvsserver tests, Perl SQLite interface unavailable'
|
||||
test_done
|
||||
exit
|
||||
}
|
||||
|
||||
unset GIT_DIR GIT_CONFIG
|
||||
|
||||
@@ -51,12 +51,10 @@ if test $? -ne 1
|
||||
then
|
||||
say 'skipping git-cvsserver tests, cvs not found'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
|
||||
say 'skipping git-cvsserver tests, Perl SQLite interface unavailable'
|
||||
test_done
|
||||
exit
|
||||
}
|
||||
|
||||
unset GIT_DIR GIT_CONFIG
|
||||
|
||||
@@ -68,7 +68,6 @@ gitweb_run () {
|
||||
perl -MEncode -e 'decode_utf8("", Encode::FB_CROAK)' >/dev/null 2>&1 || {
|
||||
say 'skipping gitweb tests, perl version is too old'
|
||||
test_done
|
||||
exit
|
||||
}
|
||||
|
||||
gitweb_init
|
||||
|
||||
@@ -14,7 +14,6 @@ if ! type cvs >/dev/null 2>&1
|
||||
then
|
||||
say 'skipping cvsimport tests, cvs not found'
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
cvsps_version=`cvsps -h 2>&1 | sed -ne 's/cvsps version //p'`
|
||||
@@ -24,12 +23,10 @@ case "$cvsps_version" in
|
||||
'')
|
||||
say 'skipping cvsimport tests, cvsps not found'
|
||||
test_done
|
||||
exit
|
||||
;;
|
||||
*)
|
||||
say 'skipping cvsimport tests, unsupported cvsps version'
|
||||
test_done
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
12
tree-diff.c
12
tree-diff.c
@@ -118,10 +118,16 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The base is a subdirectory of a path which
|
||||
* was specified, so all of them are interesting.
|
||||
* If the base is a subdirectory of a path which
|
||||
* was specified, all of them are interesting.
|
||||
*/
|
||||
return 2;
|
||||
if (!matchlen ||
|
||||
base[matchlen] == '/' ||
|
||||
match[matchlen - 1] == '/')
|
||||
return 2;
|
||||
|
||||
/* Just a random prefix match */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Does the base match? */
|
||||
|
||||
8
tree.c
8
tree.c
@@ -60,8 +60,12 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns
|
||||
/* If it doesn't match, move along... */
|
||||
if (strncmp(base, match, matchlen))
|
||||
continue;
|
||||
/* The base is a subdirectory of a path which was specified. */
|
||||
return 1;
|
||||
/* pathspecs match only at the directory boundaries */
|
||||
if (!matchlen ||
|
||||
base[matchlen] == '/' ||
|
||||
match[matchlen - 1] == '/')
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Does the base match? */
|
||||
|
||||
Reference in New Issue
Block a user