mirror of
https://github.com/git/git.git
synced 2026-03-13 10:23:30 +01:00
Merge branch 'master' of git://repo.or.cz/alt-git
This commit is contained in:
42
Documentation/RelNotes-1.5.1.5.txt
Normal file
42
Documentation/RelNotes-1.5.1.5.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
GIT v1.5.1.5 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.5.1.4
|
||||
--------------------
|
||||
|
||||
* Bugfixes
|
||||
|
||||
- git-send-email did not understand aliases file for mutt, which
|
||||
allows leading whitespaces.
|
||||
|
||||
- git-format-patch emitted Content-Type and Content-Transfer-Encoding
|
||||
headers for non ASCII contents, but failed to add MIME-Version.
|
||||
|
||||
- git-name-rev had a buffer overrun with a deep history.
|
||||
|
||||
- contributed script import-tars did not get the directory in
|
||||
tar archives interpreted correctly.
|
||||
|
||||
- git-svn was reported to segfault for many people on list and
|
||||
#git; hopefully this has been fixed.
|
||||
|
||||
- "git-svn clone" does not try to minimize the URL
|
||||
(i.e. connect to higher level hierarchy) by default, as this
|
||||
can prevent clone to fail if only part of the repository
|
||||
(e.g. 'trunk') is open to public.
|
||||
|
||||
- "git checkout branch^0" did not detach the head when you are
|
||||
already on 'branch'; backported the fix from the 'master'.
|
||||
|
||||
- "git-config section.var" did not correctly work when
|
||||
existing configuration file had both [section] and [section "name"]
|
||||
next to each other.
|
||||
|
||||
- "git clone ../other-directory" was fooled if the current
|
||||
directory $PWD points at is a symbolic link.
|
||||
|
||||
- (build) tree_entry_extract() function was both static inline
|
||||
and extern, which caused trouble compiling with Forte12
|
||||
compilers on Sun.
|
||||
|
||||
- Many many documentation fixes and updates.
|
||||
45
Documentation/RelNotes-1.5.1.6.txt
Normal file
45
Documentation/RelNotes-1.5.1.6.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
GIT v1.5.1.6 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.5.1.4
|
||||
--------------------
|
||||
|
||||
* Bugfixes
|
||||
|
||||
- git-send-email did not understand aliases file for mutt, which
|
||||
allows leading whitespaces.
|
||||
|
||||
- git-format-patch emitted Content-Type and Content-Transfer-Encoding
|
||||
headers for non ASCII contents, but failed to add MIME-Version.
|
||||
|
||||
- git-name-rev had a buffer overrun with a deep history.
|
||||
|
||||
- contributed script import-tars did not get the directory in
|
||||
tar archives interpreted correctly.
|
||||
|
||||
- git-svn was reported to segfault for many people on list and
|
||||
#git; hopefully this has been fixed.
|
||||
|
||||
- git-svn also had a bug to crash svnserve by sending a bad
|
||||
sequence of requests.
|
||||
|
||||
- "git-svn clone" does not try to minimize the URL
|
||||
(i.e. connect to higher level hierarchy) by default, as this
|
||||
can prevent clone to fail if only part of the repository
|
||||
(e.g. 'trunk') is open to public.
|
||||
|
||||
- "git checkout branch^0" did not detach the head when you are
|
||||
already on 'branch'; backported the fix from the 'master'.
|
||||
|
||||
- "git-config section.var" did not correctly work when
|
||||
existing configuration file had both [section] and [section "name"]
|
||||
next to each other.
|
||||
|
||||
- "git clone ../other-directory" was fooled if the current
|
||||
directory $PWD points at is a symbolic link.
|
||||
|
||||
- (build) tree_entry_extract() function was both static inline
|
||||
and extern, which caused trouble compiling with Forte12
|
||||
compilers on Sun.
|
||||
|
||||
- Many many documentation fixes and updates.
|
||||
@@ -1,18 +1,18 @@
|
||||
GIT v1.5.2 Release Notes (draft)
|
||||
GIT v1.5.2 Release Notes
|
||||
========================
|
||||
|
||||
Updates since v1.5.1
|
||||
--------------------
|
||||
|
||||
* Plumbing level subproject support.
|
||||
* Plumbing level superproject support.
|
||||
|
||||
You can include a subdirectory that has an independent git
|
||||
repository in your index and tree objects as a
|
||||
"subproject". This plumbing (i.e. "core") level subproject
|
||||
support explicitly excludes recursive behaviour.
|
||||
repository in your index and tree objects of your project
|
||||
("superproject"). This plumbing (i.e. "core") level
|
||||
superproject support explicitly excludes recursive behaviour.
|
||||
|
||||
The "subproject" entries in the index and trees are
|
||||
incompatible with older versions of git. Experimenting with
|
||||
The "subproject" entries in the index and trees of a superproject
|
||||
are incompatible with older versions of git. Experimenting with
|
||||
the plumbing level support is encouraged, but be warned that
|
||||
unless everybody in your project updates to this release or
|
||||
later, using this feature would make your project
|
||||
@@ -26,28 +26,30 @@ Updates since v1.5.1
|
||||
considered a binary or text (the former would be treated by
|
||||
'git diff' not to produce textual output; the latter can go
|
||||
through the line endings conversion process in repositories
|
||||
with core.autocrlf set), expand and unexpand '$ident$' keyword
|
||||
with core.autocrlf set), expand and unexpand '$Id$' keyword
|
||||
with blob object name, specify a custom 3-way merge driver,
|
||||
and specify a custom diff driver. You can also apply
|
||||
arbitrary filter to contents on check-in/check-out codepath
|
||||
but this feature is an extremely sharp-edged razor and needs
|
||||
to be handled with caution (do not use it unless you
|
||||
understand the earlier mailing list discussion on keyword
|
||||
expansion).
|
||||
expansion). These conversions apply when checking files in
|
||||
or out, and exporting via git-archive.
|
||||
|
||||
* The packfile format now optionally suports 64-bit index.
|
||||
|
||||
This release supports the "version 2" format of the .idx
|
||||
file. This is automatically enabled when a huge packfile
|
||||
needs more than 32-bit to express offsets of objects in the
|
||||
pack
|
||||
pack.
|
||||
|
||||
* Comes with an updated git-gui 0.7.0
|
||||
* Comes with an updated git-gui 0.7.1
|
||||
|
||||
* Updated gitweb:
|
||||
|
||||
- can show combined diff for merges;
|
||||
- uses font size of user's preference, not hardcoded in pixels;
|
||||
- can now 'grep';
|
||||
|
||||
* New commands and options.
|
||||
|
||||
@@ -114,7 +116,7 @@ Updates since v1.5.1
|
||||
- Local "git fetch" from a repository whose object store is
|
||||
one of the alternates (e.g. fetching from the origin in a
|
||||
repository created with "git clone -l -s") avoids
|
||||
downloading objects unnecessary.
|
||||
downloading objects unnecessarily.
|
||||
|
||||
- "git blame" uses .mailmap to canonicalize the author name
|
||||
just like "git shortlog" does.
|
||||
@@ -124,7 +126,7 @@ Updates since v1.5.1
|
||||
|
||||
- "git cherry-pick" and "git revert" does not use .msg file in
|
||||
the working tree to prepare commit message; instead it uses
|
||||
$GIT_DIR/MERGE_MSG as other commands.
|
||||
$GIT_DIR/MERGE_MSG as other commands do.
|
||||
|
||||
* Builds
|
||||
|
||||
@@ -134,7 +136,7 @@ Updates since v1.5.1
|
||||
- gitk and git-gui can be configured out.
|
||||
|
||||
- Generated documentation pages automatically get version
|
||||
information from GIT_VERSION
|
||||
information from GIT_VERSION.
|
||||
|
||||
- Parallel build with "make -j" descending into subdirectory
|
||||
was fixed.
|
||||
@@ -151,11 +153,13 @@ Updates since v1.5.1
|
||||
- The recursive merge strategy updated a worktree file that
|
||||
was changed identically in two branches, when one of them
|
||||
renamed it. We do not do that when there is no rename, so
|
||||
match that behaviour.
|
||||
match that behaviour. This avoids excessive rebuilds.
|
||||
|
||||
- The default pack depth has been increased to 50, as the
|
||||
recent addition of delta_base_cache makes deeper delta chains
|
||||
much less expensive to access.
|
||||
much less expensive to access. Depending on the project, it was
|
||||
reported that this reduces the resulting pack file by 10%
|
||||
or so.
|
||||
|
||||
|
||||
Fixes since v1.5.1
|
||||
@@ -188,12 +192,6 @@ this release, unless otherwise noted.
|
||||
|
||||
- "git clean -d -X" now does not remove non-excluded directories.
|
||||
|
||||
* Documentation updates
|
||||
|
||||
* Performance Tweaks
|
||||
|
||||
--
|
||||
exec >/var/tmp/1
|
||||
O=v1.5.2-rc2-91-g616e40b
|
||||
echo O=`git describe refs/heads/master`
|
||||
git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint
|
||||
- rebasing (without -m) a series that changes a symlink to a directory
|
||||
in the middle of a path confused git-apply greatly and refused to
|
||||
operate.
|
||||
|
||||
@@ -57,8 +57,11 @@ OPTIONS
|
||||
the index.
|
||||
|
||||
-u::
|
||||
Update all files that git already knows about. This is what
|
||||
"git commit -a" does in preparation for making a commit.
|
||||
Update only files that git already knows about. This is similar
|
||||
to what "git commit -a" does in preparation for making a commit,
|
||||
except that the update is limited to paths specified on the
|
||||
command line. If no paths are specified, all tracked files are
|
||||
updated.
|
||||
|
||||
\--::
|
||||
This option can be used to separate command-line options from
|
||||
@@ -66,6 +69,15 @@ OPTIONS
|
||||
for command-line options).
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The optional configuration variable 'core.excludesfile' indicates a path to a
|
||||
file containing patterns of file names to exclude from git-add, similar to
|
||||
$GIT_DIR/info/exclude. Patterns in the exclude file are used in addition to
|
||||
those in info/exclude. See link:repository-layout.html[repository layout].
|
||||
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
git-add Documentation/\\*.txt::
|
||||
|
||||
@@ -9,9 +9,10 @@ git-am - Apply a series of patches from a mailbox
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-am' [--signoff] [--dotest=<dir>] [--utf8 | --no-utf8] [--binary] [--3way]
|
||||
[--interactive] [--whitespace=<option>] [-C<n>] [-p<n>]
|
||||
<mbox>...
|
||||
'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]
|
||||
[--3way] [--interactive] [--binary]
|
||||
[--whitespace=<option>] [-C<n>] [-p<n>]
|
||||
<mbox>...
|
||||
'git-am' [--skip | --resolved]
|
||||
|
||||
DESCRIPTION
|
||||
@@ -40,7 +41,7 @@ OPTIONS
|
||||
-u, --utf8::
|
||||
Pass `-u` flag to `git-mailinfo` (see gitlink:git-mailinfo[1]).
|
||||
The proposed commit log message taken from the e-mail
|
||||
are re-coded into UTF-8 encoding (configuration variable
|
||||
is re-coded into UTF-8 encoding (configuration variable
|
||||
`i18n.commitencoding` can be used to specify project's
|
||||
preferred encoding if it is not UTF-8).
|
||||
+
|
||||
@@ -51,31 +52,33 @@ default. You could use `--no-utf8` to override this.
|
||||
Pass `-n` flag to `git-mailinfo` (see
|
||||
gitlink:git-mailinfo[1]).
|
||||
|
||||
-b, --binary::
|
||||
Pass `--allow-binary-replacement` flag to `git-apply`
|
||||
(see gitlink:git-apply[1]).
|
||||
|
||||
-3, --3way::
|
||||
When the patch does not apply cleanly, fall back on
|
||||
3-way merge, if the patch records the identity of blobs
|
||||
it is supposed to apply to, and we have those blobs
|
||||
locally.
|
||||
available locally.
|
||||
|
||||
-b, --binary::
|
||||
Pass `--allow-binary-replacement` flag to `git-apply`
|
||||
(see gitlink:git-apply[1]).
|
||||
|
||||
--whitespace=<option>::
|
||||
This flag is passed to the `git-apply` (see gitlink:git-apply[1])
|
||||
program that applies
|
||||
the patch.
|
||||
|
||||
-C<n>, -p<n>::
|
||||
These flags are passed to the `git-apply` (see gitlink:git-apply[1])
|
||||
program that applies
|
||||
the patch.
|
||||
|
||||
-i, --interactive::
|
||||
Run interactively.
|
||||
|
||||
--skip::
|
||||
Skip the current patch. This is only meaningful when
|
||||
restarting an aborted patch.
|
||||
|
||||
--whitespace=<option>::
|
||||
This flag is passed to the `git-apply` program that applies
|
||||
the patch.
|
||||
|
||||
-C<n>, -p<n>::
|
||||
These flags are passed to the `git-apply` program that applies
|
||||
the patch.
|
||||
|
||||
-i, --interactive::
|
||||
Run interactively, just like git-applymbox.
|
||||
|
||||
-r, --resolved::
|
||||
After a patch failure (e.g. attempting to apply
|
||||
conflicting patch), the user has applied it by hand and
|
||||
@@ -126,7 +129,7 @@ to crunch. Upon seeing the first patch that does not apply, it
|
||||
aborts in the middle, just like 'git-applymbox' does. You can
|
||||
recover from this in one of two ways:
|
||||
|
||||
. skip the current one by re-running the command with '--skip'
|
||||
. skip the current patch by re-running the command with '--skip'
|
||||
option.
|
||||
|
||||
. hand resolve the conflict in the working directory, and update
|
||||
|
||||
@@ -31,7 +31,7 @@ OPTIONS
|
||||
whitespaces, (3) '[' up to ']', typically '[PATCH]', and
|
||||
then prepends "[PATCH] ". This flag forbids this
|
||||
munging, and is most useful when used to read back 'git
|
||||
format-patch --mbox' output.
|
||||
format-patch -k' output.
|
||||
|
||||
-m::
|
||||
Patches are applied with `git-apply` command, and unless
|
||||
|
||||
@@ -8,6 +8,7 @@ git-archive - Creates an archive of files from a named tree
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
|
||||
[--remote=<repo>] <tree-ish> [path...]
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ $ git branch -D test <2>
|
||||
+
|
||||
<1> delete remote-tracking branches "todo", "html", "man"
|
||||
<2> delete "test" branch even if the "master" branch does not have all
|
||||
commits from todo branch.
|
||||
commits from test branch.
|
||||
|
||||
|
||||
Notes
|
||||
|
||||
@@ -8,6 +8,7 @@ git-bundle - Move objects and refs by archive
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-bundle' create <file> [git-rev-list args]
|
||||
'git-bundle' verify <file>
|
||||
'git-bundle' list-heads <file> [refname...]
|
||||
|
||||
@@ -132,7 +132,7 @@ Make a local clone that borrows from the current directory, without checking thi
|
||||
+
|
||||
------------
|
||||
$ git clone -l -s -n . ../copy
|
||||
$ cd copy
|
||||
$ cd ../copy
|
||||
$ git show-branch
|
||||
------------
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ separated with a single space are given.
|
||||
This flag causes "git-diff-tree --stdin" to also show
|
||||
the commit message before the differences.
|
||||
|
||||
include::pretty-formats.txt[]
|
||||
include::pretty-options.txt[]
|
||||
|
||||
--no-commit-id::
|
||||
git-diff-tree outputs a line with the commit ID when
|
||||
@@ -104,6 +104,9 @@ include::pretty-formats.txt[]
|
||||
if the diff itself is empty.
|
||||
|
||||
|
||||
include::pretty-formats.txt[]
|
||||
|
||||
|
||||
Limiting Output
|
||||
---------------
|
||||
If you're only interested in differences in a subset of files, for
|
||||
|
||||
@@ -8,6 +8,7 @@ git-fmt-merge-msg - Produce a merge commit message
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
git-fmt-merge-msg [--summary | --no-summary] <$GIT_DIR/FETCH_HEAD
|
||||
git-fmt-merge-msg [--summary | --no-summray] -F <file>
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@ git-for-each-ref - Output information on each ref
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-for-each-ref' [--count=<count>]\* [--shell|--perl|--python|--tcl] [--sort=<key>]\* [--format=<format>] [<pattern>]
|
||||
[verse]
|
||||
'git-for-each-ref' [--count=<count>]\*
|
||||
[--shell|--perl|--python|--tcl]
|
||||
[--sort=<key>]\* [--format=<format>] [<pattern>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
@@ -8,8 +8,10 @@ git-index-pack - Build pack index file for an existing packed archive
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-index-pack' [-v] [-o <index-file>] <pack-file>
|
||||
'git-index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>] [<pack-file>]
|
||||
'git-index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
|
||||
[<pack-file>]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
@@ -7,8 +7,9 @@ git-instaweb - Instantly browse your working repository in gitweb
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-instaweb' [--local] [--httpd=<httpd>] [--port=<port>] [--browser=<browser>]
|
||||
|
||||
[verse]
|
||||
'git-instaweb' [--local] [--httpd=<httpd>] [--port=<port>]
|
||||
[--browser=<browser>]
|
||||
'git-instaweb' [--start] [--stop] [--restart]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
@@ -8,7 +8,9 @@ git-local-fetch - Duplicate another git repository on a local system
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-local-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [-l] [-s] [-n] commit-id path
|
||||
[verse]
|
||||
'git-local-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [-l] [-s] [-n]
|
||||
commit-id path
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
@@ -25,7 +25,7 @@ This manual page describes only the most frequently used options.
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
include::pretty-formats.txt[]
|
||||
include::pretty-options.txt[]
|
||||
|
||||
-<n>::
|
||||
Limits the number of commits to show.
|
||||
@@ -58,6 +58,9 @@ include::pretty-formats.txt[]
|
||||
Show only commits that affect the specified paths.
|
||||
|
||||
|
||||
include::pretty-formats.txt[]
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
git log --no-merges::
|
||||
|
||||
@@ -30,7 +30,7 @@ OPTIONS
|
||||
whitespaces, (3) '[' up to ']', typically '[PATCH]', and
|
||||
then prepends "[PATCH] ". This flag forbids this
|
||||
munging, and is most useful when used to read back 'git
|
||||
format-patch --mbox' output.
|
||||
format-patch -k' output.
|
||||
|
||||
-u::
|
||||
The commit log message, author name and author email are
|
||||
|
||||
@@ -8,6 +8,7 @@ git-name-rev - Find symbolic names for given revs
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-name-rev' [--tags] [--refs=<pattern>]
|
||||
( --all | --stdin | <committish>... )
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ git-p4import - Import a Perforce repository into git
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
`git-p4import` [-q|-v] [--notags] [--authors <file>] [-t <timezone>] <//p4repo/path> <branch>
|
||||
|
||||
[verse]
|
||||
`git-p4import` [-q|-v] [--notags] [--authors <file>] [-t <timezone>]
|
||||
<//p4repo/path> <branch>
|
||||
`git-p4import` --stitch <//p4repo/path>
|
||||
|
||||
`git-p4import`
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@ git-push - Update remote refs along with associated objects
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-push' [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]
|
||||
[verse]
|
||||
'git-push' [--all] [--tags] [--receive-pack=<git-receive-pack>]
|
||||
[--repo=all] [-f | --force] [-v] [<repository> <refspec>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
@@ -7,8 +7,8 @@ git-rebase - Forward-port local commits to the updated upstream head
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-rebase' [-v] [--merge] [-C<n>] [--onto <newbase>] <upstream> [<branch>]
|
||||
|
||||
'git-rebase' --continue | --skip | --abort
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
@@ -87,7 +87,7 @@ Using these options, gitlink:git-rev-list[1] will act similar to the
|
||||
more specialized family of commit log tools: gitlink:git-log[1],
|
||||
gitlink:git-show[1], and gitlink:git-whatchanged[1]
|
||||
|
||||
include::pretty-formats.txt[]
|
||||
include::pretty-options.txt[]
|
||||
|
||||
--relative-date::
|
||||
|
||||
@@ -207,12 +207,12 @@ limiting may be applied.
|
||||
--author='pattern', --committer='pattern'::
|
||||
|
||||
Limit the commits output to ones with author/committer
|
||||
header lines that match the specified pattern.
|
||||
header lines that match the specified pattern (regular expression).
|
||||
|
||||
--grep='pattern'::
|
||||
|
||||
Limit the commits output to ones with log message that
|
||||
matches the specified pattern.
|
||||
matches the specified pattern (regular expression).
|
||||
|
||||
--remove-empty::
|
||||
|
||||
@@ -367,6 +367,10 @@ These options are mostly targeted for packing of git repositories.
|
||||
Only useful with '--objects'; print the object IDs that are not
|
||||
in packs.
|
||||
|
||||
|
||||
include::pretty-formats.txt[]
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>
|
||||
|
||||
@@ -38,6 +38,9 @@ OPTIONS
|
||||
For a more complete list of ways to spell object names, see
|
||||
"SPECIFYING REVISIONS" section in gitlink:git-rev-parse[1].
|
||||
|
||||
include::pretty-options.txt[]
|
||||
|
||||
|
||||
include::pretty-formats.txt[]
|
||||
|
||||
|
||||
|
||||
@@ -35,42 +35,43 @@ documentation can be viewed at
|
||||
ifdef::stalenotes[]
|
||||
[NOTE]
|
||||
============
|
||||
You are reading the documentation for the latest version of git.
|
||||
|
||||
You are reading the documentation for the latest (possibly
|
||||
unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:RelNotes-1.5.1.txt[release notes for 1.5.1]
|
||||
* link:v1.5.2/git.html[documentation for release 1.5.2]
|
||||
|
||||
* link:v1.5.1.4/git.html[documentation for release 1.5.1.4]
|
||||
* release notes for
|
||||
link:RelNotes-1.5.2.txt[1.5.2].
|
||||
|
||||
* link:RelNotes-1.5.1.4.txt[release notes for 1.5.1.4]
|
||||
* link:v1.5.1.6/git.html[documentation for release 1.5.1.6]
|
||||
|
||||
* link:RelNotes-1.5.1.3.txt[release notes for 1.5.1.3]
|
||||
* release notes for
|
||||
link:RelNotes-1.5.1.6.txt[1.5.1.6],
|
||||
link:RelNotes-1.5.1.5.txt[1.5.1.5],
|
||||
link:RelNotes-1.5.1.4.txt[1.5.1.4],
|
||||
link:RelNotes-1.5.1.3.txt[1.5.1.3],
|
||||
link:RelNotes-1.5.1.2.txt[1.5.1.2],
|
||||
link:RelNotes-1.5.1.1.txt[1.5.1.1],
|
||||
link:RelNotes-1.5.1.txt[1.5.1].
|
||||
|
||||
* link:RelNotes-1.5.1.2.txt[release notes for 1.5.1.2]
|
||||
* link:v1.5.0.7/git.html[documentation for release 1.5.0.7]
|
||||
|
||||
* link:RelNotes-1.5.1.1.txt[release notes for 1.5.1.1]
|
||||
* release notes for
|
||||
link:RelNotes-1.5.0.7.txt[1.5.0.7],
|
||||
link:RelNotes-1.5.0.6.txt[1.5.0.6],
|
||||
link:RelNotes-1.5.0.5.txt[1.5.0.5],
|
||||
link:RelNotes-1.5.0.3.txt[1.5.0.3],
|
||||
link:RelNotes-1.5.0.2.txt[1.5.0.2],
|
||||
link:RelNotes-1.5.0.1.txt[1.5.0.1],
|
||||
link:RelNotes-1.5.0.txt[1.5.0].
|
||||
|
||||
* link:RelNotes-1.5.0.7.txt[release notes for 1.5.0.7]
|
||||
|
||||
* link:RelNotes-1.5.0.6.txt[release notes for 1.5.0.6]
|
||||
|
||||
* link:RelNotes-1.5.0.5.txt[release notes for 1.5.0.5]
|
||||
|
||||
* link:RelNotes-1.5.0.3.txt[release notes for 1.5.0.3]
|
||||
|
||||
* link:RelNotes-1.5.0.2.txt[release notes for 1.5.0.2]
|
||||
|
||||
* link:RelNotes-1.5.0.1.txt[release notes for 1.5.0.1]
|
||||
|
||||
* link:RelNotes-1.5.0.txt[release notes for 1.5.0]
|
||||
|
||||
* link:v1.4.4.4/git.html[documentation for release 1.4.4.4]
|
||||
|
||||
* link:v1.3.3/git.html[documentation for release 1.3.3]
|
||||
|
||||
* link:v1.2.6/git.html[documentation for release 1.2.6]
|
||||
|
||||
* link:v1.0.13/git.html[documentation for release 1.0.13]
|
||||
* documentation for release link:v1.4.4.4/git.html[1.4.4.4],
|
||||
link:v1.3.3/git.html[1.3.3],
|
||||
link:v1.2.6/git.html[1.2.6],
|
||||
link:v1.0.13/git.html[1.0.13].
|
||||
|
||||
============
|
||||
|
||||
|
||||
@@ -138,11 +138,11 @@ upon checkout.
|
||||
^^^^^^^
|
||||
|
||||
When the attribute `ident` is set to a path, git replaces
|
||||
`$ident$` in the blob object with `$ident:`, followed by
|
||||
`$Id$` in the blob object with `$Id:`, followed by
|
||||
40-character hexadecimal blob object name, followed by a dollar
|
||||
sign `$` upon checkout. Any byte sequence that begins with
|
||||
`$ident:` and ends with `$` in the worktree file is replaced
|
||||
with `$ident$` upon check-in.
|
||||
`$Id:` and ends with `$` in the worktree file is replaced
|
||||
with `$Id$` upon check-in.
|
||||
|
||||
|
||||
Interaction between checkin/checkout attributes
|
||||
|
||||
@@ -2,12 +2,12 @@ GIT Glossary
|
||||
============
|
||||
|
||||
[[def_alternate_object_database]]alternate object database::
|
||||
Via the alternates mechanism, a <<def_repository,repository>> can
|
||||
inherit part of its <<def_object_database,object database>> from another
|
||||
<<def_object_database,object database>>, which is called "alternate".
|
||||
Via the alternates mechanism, a <<def_repository,repository>>
|
||||
can inherit part of its <<def_object_database,object database>>
|
||||
from another object database, which is called "alternate".
|
||||
|
||||
[[def_bare_repository]]bare repository::
|
||||
A <<def_bare_repository,bare repository>> is normally an appropriately
|
||||
A bare repository is normally an appropriately
|
||||
named <<def_directory,directory>> with a `.git` suffix that does not
|
||||
have a locally checked-out copy of any of the files under
|
||||
<<def_revision,revision>> control. That is, all of the `git`
|
||||
@@ -21,10 +21,15 @@ GIT Glossary
|
||||
Untyped <<def_object,object>>, e.g. the contents of a file.
|
||||
|
||||
[[def_branch]]branch::
|
||||
A non-cyclical graph of revisions, i.e. the complete history of a
|
||||
particular <<def_revision,revision>>, which is called the
|
||||
branch <<def_head,head>>. The heads
|
||||
are stored in `$GIT_DIR/refs/heads/`.
|
||||
A "branch" is an active line of development. The most recent
|
||||
<<def_commit,commit>> on a branch is referred to as the tip of
|
||||
that branch. The tip of the branch is referenced by a branch
|
||||
<<def_head,head>>, which moves forward as additional development
|
||||
is done on the branch. A single git
|
||||
<<def_repository,repository>> can track an arbitrary number of
|
||||
branches, but your <<def_working_tree,working tree>> is
|
||||
associated with just one of them (the "current" or "checked out"
|
||||
branch), and <<def_HEAD,HEAD>> points to that branch.
|
||||
|
||||
[[def_cache]]cache::
|
||||
Obsolete for: <<def_index,index>>.
|
||||
@@ -50,18 +55,25 @@ GIT Glossary
|
||||
as a new series of changes on top of different codebase. In GIT, this is
|
||||
performed by "git cherry-pick" command to extract the change introduced
|
||||
by an existing <<def_commit,commit>> and to record it based on the tip
|
||||
of the current <<def_branch,branch>> as a new <<def_commit,commit>>.
|
||||
of the current <<def_branch,branch>> as a new commit.
|
||||
|
||||
[[def_clean]]clean::
|
||||
A <<def_working_tree,working tree>> is <<def_clean,clean>>, if it
|
||||
A <<def_working_tree,working tree>> is clean, if it
|
||||
corresponds to the <<def_revision,revision>> referenced by the current
|
||||
<<def_head,head>>. Also see "<<def_dirty,dirty>>".
|
||||
|
||||
[[def_commit]]commit::
|
||||
As a verb: The action of storing the current state of the
|
||||
<<def_index,index>> in the <<def_object_database,object database>>. The
|
||||
result is a <<def_revision,revision>>. As a noun: Short hand for
|
||||
<<def_commit_object,commit object>>.
|
||||
As a noun: A single point in the
|
||||
git history; the entire history of a project is represented as a
|
||||
set of interrelated commits. The word "commit" is often
|
||||
used by git in the same places other revision control systems
|
||||
use the words "revision" or "version". Also used as a short
|
||||
hand for <<def_commit_object,commit object>>.
|
||||
+
|
||||
As a verb: The action of storing a new snapshot of the project's
|
||||
state in the git history, by creating a new commit representing the current
|
||||
state of the <<def_index,index>> and advancing <<def_HEAD,HEAD>>
|
||||
to point at the new commit.
|
||||
|
||||
[[def_commit_object]]commit object::
|
||||
An <<def_object,object>> which contains the information about a
|
||||
@@ -77,16 +89,22 @@ GIT Glossary
|
||||
[[def_DAG]]DAG::
|
||||
Directed acyclic graph. The <<def_commit,commit>> objects form a
|
||||
directed acyclic graph, because they have parents (directed), and the
|
||||
graph of <<def_commit,commit>> objects is acyclic (there is no
|
||||
graph of commit objects is acyclic (there is no
|
||||
<<def_chain,chain>> which begins and ends with the same
|
||||
<<def_object,object>>).
|
||||
|
||||
[[def_dangling_object]]dangling object::
|
||||
An <<def_unreachable_object,unreachable object>> which is not
|
||||
<<def_reachable,reachable>> even from other unreachable objects; a
|
||||
<<def_dangling_object,dangling object>> has no references to it from any
|
||||
dangling object has no references to it from any
|
||||
reference or <<def_object,object>> in the <<def_repository,repository>>.
|
||||
|
||||
[[def_detached_HEAD]]detached HEAD::
|
||||
Normally the <<def_HEAD,HEAD>> stores the name of a
|
||||
<<def_branch,branch>>. However, git also allows you to check
|
||||
out an arbitrary commit that isn't necessarily the tip of any
|
||||
particular branch. In this case HEAD is said to be "detached".
|
||||
|
||||
[[def_dircache]]dircache::
|
||||
You are *waaaaay* behind.
|
||||
|
||||
@@ -94,7 +112,7 @@ GIT Glossary
|
||||
The list you get with "ls" :-)
|
||||
|
||||
[[def_dirty]]dirty::
|
||||
A <<def_working_tree,working tree>> is said to be <<def_dirty,dirty>> if
|
||||
A <<def_working_tree,working tree>> is said to be "dirty" if
|
||||
it contains modifications which have not been committed to the current
|
||||
<<def_branch,branch>>.
|
||||
|
||||
@@ -109,16 +127,16 @@ GIT Glossary
|
||||
<<def_branch,branch>>'s changes that happen to be a descendant of what
|
||||
you have. In such these cases, you do not make a new <<def_merge,merge>>
|
||||
<<def_commit,commit>> but instead just update to his
|
||||
<<def_revision,revision>>. This will happen frequently on a
|
||||
revision. This will happen frequently on a
|
||||
<<def_tracking_branch,tracking branch>> of a remote
|
||||
<<def_repository,repository>>.
|
||||
|
||||
[[def_fetch]]fetch::
|
||||
Fetching a <<def_branch,branch>> means to get the
|
||||
<<def_branch,branch>>'s <<def_head_ref,head ref>> from a remote
|
||||
<<def_repository,repository>>, to find out which objects are missing
|
||||
from the local <<def_object_database,object database>>, and to get them,
|
||||
too.
|
||||
branch's <<def_head_ref,head ref>> from a remote
|
||||
<<def_repository,repository>>, to find out which objects are
|
||||
missing from the local <<def_object_database,object database>>,
|
||||
and to get them, too. See also gitlink:git-fetch[1].
|
||||
|
||||
[[def_file_system]]file system::
|
||||
Linus Torvalds originally designed git to be a user space file system,
|
||||
@@ -132,61 +150,83 @@ GIT Glossary
|
||||
Grafts enables two otherwise different lines of development to be joined
|
||||
together by recording fake ancestry information for commits. This way
|
||||
you can make git pretend the set of parents a <<def_commit,commit>> has
|
||||
is different from what was recorded when the <<def_commit,commit>> was
|
||||
is different from what was recorded when the commit was
|
||||
created. Configured via the `.git/info/grafts` file.
|
||||
|
||||
[[def_hash]]hash::
|
||||
In git's context, synonym to <<def_object_name,object name>>.
|
||||
|
||||
[[def_head]]head::
|
||||
The top of a <<def_branch,branch>>. It contains a <<def_ref,ref>> to the
|
||||
corresponding <<def_commit_object,commit object>>.
|
||||
A named reference to the <<def_commit,commit>> at the tip of a
|
||||
<<def_branch,branch>>. Heads are stored in
|
||||
`$GIT_DIR/refs/heads/`, except when using packed refs. (See
|
||||
gitlink:git-pack-refs[1].)
|
||||
|
||||
[[def_HEAD]]HEAD::
|
||||
The current branch. In more detail: Your <<def_working_tree,
|
||||
working tree>> is normally derived from the state of the tree
|
||||
referred to by HEAD. HEAD is a reference to one of the
|
||||
<<def_head,heads>> in your repository, except when using a
|
||||
<<def_detached_HEAD,detached HEAD>>, in which case it may
|
||||
reference an arbitrary commit.
|
||||
|
||||
[[def_head_ref]]head ref::
|
||||
A <<def_ref,ref>> pointing to a <<def_head,head>>. Often, this is
|
||||
abbreviated to "<<def_head,head>>". Head refs are stored in
|
||||
`$GIT_DIR/refs/heads/`.
|
||||
A synonym for <<def_head,head>>.
|
||||
|
||||
[[def_hook]]hook::
|
||||
During the normal execution of several git commands, call-outs are made
|
||||
to optional scripts that allow a developer to add functionality or
|
||||
checking. Typically, the hooks allow for a command to be pre-verified
|
||||
and potentially aborted, and allow for a post-notification after the
|
||||
operation is done. The <<def_hook,hook>> scripts are found in the
|
||||
operation is done. The hook scripts are found in the
|
||||
`$GIT_DIR/hooks/` <<def_directory,directory>>, and are enabled by simply
|
||||
making them executable.
|
||||
|
||||
[[def_index]]index::
|
||||
A collection of files with stat information, whose contents are stored
|
||||
as objects. The <<def_index,index>> is a stored version of your working
|
||||
as objects. The index is a stored version of your working
|
||||
<<def_tree,tree>>. Truth be told, it can also contain a second, and even
|
||||
a third version of a <<def_working_tree,working tree>>, which are used
|
||||
when merging.
|
||||
|
||||
[[def_index_entry]]index entry::
|
||||
The information regarding a particular file, stored in the
|
||||
<<def_index,index>>. An <<def_index_entry,index entry>> can be unmerged,
|
||||
if a <<def_merge,merge>> was started, but not yet finished (i.e. if the
|
||||
<<def_index,index>> contains multiple versions of that file).
|
||||
<<def_index,index>>. An index entry can be unmerged, if a
|
||||
<<def_merge,merge>> was started, but not yet finished (i.e. if
|
||||
the index contains multiple versions of that file).
|
||||
|
||||
[[def_master]]master::
|
||||
The default development <<def_branch,branch>>. Whenever you create a git
|
||||
<<def_repository,repository>>, a <<def_branch,branch>> named
|
||||
"<<def_master,master>>" is created, and becomes the active
|
||||
<<def_branch,branch>>. In most cases, this contains the local
|
||||
development, though that is purely conventional and not required.
|
||||
The default development <<def_branch,branch>>. Whenever you
|
||||
create a git <<def_repository,repository>>, a branch named
|
||||
"master" is created, and becomes the active branch. In most
|
||||
cases, this contains the local development, though that is
|
||||
purely by convention and is not required.
|
||||
|
||||
[[def_merge]]merge::
|
||||
To <<def_merge,merge>> branches means to try to accumulate the changes
|
||||
since a common ancestor and apply them to the first
|
||||
<<def_branch,branch>>. An automatic <<def_merge,merge>> uses heuristics
|
||||
to accomplish that. Evidently, an automatic <<def_merge,merge>> can
|
||||
fail.
|
||||
As a verb: To bring the contents of another
|
||||
<<def_branch,branch>> (possibly from an external
|
||||
<<def_repository,repository>>) into the current branch. In the
|
||||
case where the merged-in branch is from a different repository,
|
||||
this is done by first <<def_fetch,fetching>> the remote branch
|
||||
and then merging the result into the current branch. This
|
||||
combination of fetch and merge operations is called a
|
||||
<<def_pull,pull>>. Merging is performed by an automatic process
|
||||
that identifies changes made since the branches diverged, and
|
||||
then applies all those changes together. In cases where changes
|
||||
conflict, manual intervention may be required to complete the
|
||||
merge.
|
||||
+
|
||||
As a noun: unless it is a <<def_fast_forward,fast forward>>, a
|
||||
successful merge results in the creation of a new <<def_commit,commit>>
|
||||
representing the result of the merge, and having as
|
||||
<<def_parent,parents>> the tips of the merged <<def_branch,branches>>.
|
||||
This commit is referred to as a "merge commit", or sometimes just a
|
||||
"merge".
|
||||
|
||||
[[def_object]]object::
|
||||
The unit of storage in git. It is uniquely identified by the
|
||||
<<def_SHA1,SHA1>> of its contents. Consequently, an
|
||||
<<def_object,object>> can not be changed.
|
||||
object can not be changed.
|
||||
|
||||
[[def_object_database]]object database::
|
||||
Stores a set of "objects", and an individual <<def_object,object>> is
|
||||
@@ -198,9 +238,9 @@ GIT Glossary
|
||||
|
||||
[[def_object_name]]object name::
|
||||
The unique identifier of an <<def_object,object>>. The <<def_hash,hash>>
|
||||
of the <<def_object,object>>'s contents using the Secure Hash Algorithm
|
||||
of the object's contents using the Secure Hash Algorithm
|
||||
1 and usually represented by the 40 character hexadecimal encoding of
|
||||
the <<def_hash,hash>> of the <<def_object,object>> (possibly followed by
|
||||
the <<def_hash,hash>> of the object (possibly followed by
|
||||
a white space).
|
||||
|
||||
[[def_object_type]]object type::
|
||||
@@ -215,7 +255,7 @@ GIT Glossary
|
||||
[[def_origin]]origin::
|
||||
The default upstream <<def_repository,repository>>. Most projects have
|
||||
at least one upstream project which they track. By default
|
||||
'<<def_origin,origin>>' is used for that purpose. New upstream updates
|
||||
'origin' is used for that purpose. New upstream updates
|
||||
will be fetched into remote tracking branches named
|
||||
origin/name-of-upstream-branch, which you can see using
|
||||
"git <<def_branch,branch>> -r".
|
||||
@@ -227,7 +267,7 @@ GIT Glossary
|
||||
[[def_pack_index]]pack index::
|
||||
The list of identifiers, and other information, of the objects in a
|
||||
<<def_pack,pack>>, to assist in efficiently accessing the contents of a
|
||||
<<def_pack,pack>>.
|
||||
pack.
|
||||
|
||||
[[def_parent]]parent::
|
||||
A <<def_commit_object,commit object>> contains a (possibly empty) list
|
||||
@@ -247,29 +287,29 @@ GIT Glossary
|
||||
[[def_porcelain]]porcelain::
|
||||
Cute name for programs and program suites depending on
|
||||
<<def_core_git,core git>>, presenting a high level access to
|
||||
<<def_core_git,core git>>. Porcelains expose more of a <<def_SCM,SCM>>
|
||||
core git. Porcelains expose more of a <<def_SCM,SCM>>
|
||||
interface than the <<def_plumbing,plumbing>>.
|
||||
|
||||
[[def_pull]]pull::
|
||||
Pulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and
|
||||
<<def_merge,merge>> it.
|
||||
<<def_merge,merge>> it. See also gitlink:git-pull[1].
|
||||
|
||||
[[def_push]]push::
|
||||
Pushing a <<def_branch,branch>> means to get the <<def_branch,branch>>'s
|
||||
Pushing a <<def_branch,branch>> means to get the branch's
|
||||
<<def_head_ref,head ref>> from a remote <<def_repository,repository>>,
|
||||
find out if it is an ancestor to the <<def_branch,branch>>'s local
|
||||
<<def_head_ref,head ref>> is a direct, and in that case, putting all
|
||||
find out if it is an ancestor to the branch's local
|
||||
head ref is a direct, and in that case, putting all
|
||||
objects, which are <<def_reachable,reachable>> from the local
|
||||
<<def_head_ref,head ref>>, and which are missing from the remote
|
||||
<<def_repository,repository>>, into the remote
|
||||
head ref, and which are missing from the remote
|
||||
repository, into the remote
|
||||
<<def_object_database,object database>>, and updating the remote
|
||||
<<def_head_ref,head ref>>. If the remote <<def_head,head>> is not an
|
||||
ancestor to the local <<def_head,head>>, the <<def_push,push>> fails.
|
||||
head ref. If the remote <<def_head,head>> is not an
|
||||
ancestor to the local head, the push fails.
|
||||
|
||||
[[def_reachable]]reachable::
|
||||
All of the ancestors of a given <<def_commit,commit>> are said to be
|
||||
<<def_reachable,reachable>> from that <<def_commit,commit>>. More
|
||||
generally, one <<def_object,object>> is <<def_reachable,reachable>> from
|
||||
"reachable" from that commit. More
|
||||
generally, one <<def_object,object>> is reachable from
|
||||
another if we can reach the one from the other by a <<def_chain,chain>>
|
||||
that follows <<def_tag,tags>> to whatever they tag,
|
||||
<<def_commit_object,commits>> to their parents or trees, and
|
||||
@@ -288,24 +328,23 @@ GIT Glossary
|
||||
|
||||
[[def_refspec]]refspec::
|
||||
A <<def_refspec,refspec>> is used by <<def_fetch,fetch>> and
|
||||
<<def_push,push>> to describe the mapping between remote <<def_ref,ref>>
|
||||
and local <<def_ref,ref>>. They are combined with a colon in the format
|
||||
<src>:<dst>, preceded by an optional plus sign, +. For example: `git
|
||||
fetch $URL refs/heads/master:refs/heads/origin` means
|
||||
"grab the master <<def_branch,branch>> <<def_head,head>>
|
||||
from the $URL and store it as my origin
|
||||
<<def_branch,branch>> <<def_head,head>>". And `git <<def_push,push>>
|
||||
$URL refs/heads/master:refs/heads/to-upstream` means
|
||||
"publish my master <<def_branch,branch>>
|
||||
<<def_head,head>> as to-upstream <<def_branch,branch>> at $URL". See
|
||||
also gitlink:git-push[1]
|
||||
<<def_push,push>> to describe the mapping between remote
|
||||
<<def_ref,ref>> and local ref. They are combined with a colon in
|
||||
the format <src>:<dst>, preceded by an optional plus sign, +.
|
||||
For example: `git fetch $URL
|
||||
refs/heads/master:refs/heads/origin` means "grab the master
|
||||
<<def_branch,branch>> <<def_head,head>> from the $URL and store
|
||||
it as my origin branch head". And `git push
|
||||
$URL refs/heads/master:refs/heads/to-upstream` means "publish my
|
||||
master branch head as to-upstream branch at $URL". See also
|
||||
gitlink:git-push[1]
|
||||
|
||||
[[def_repository]]repository::
|
||||
A collection of refs together with an <<def_object_database,object
|
||||
database>> containing all objects which are <<def_reachable,reachable>>
|
||||
from the refs, possibly accompanied by meta data from one or more
|
||||
porcelains. A <<def_repository,repository>> can share an
|
||||
<<def_object_database,object database>> with other repositories.
|
||||
A collection of refs together with an
|
||||
<<def_object_database,object database>> containing all objects
|
||||
which are <<def_reachable,reachable>> from the refs, possibly
|
||||
accompanied by meta data from one or more porcelains. A
|
||||
repository can share an object database with other repositories.
|
||||
|
||||
[[def_resolve]]resolve::
|
||||
The action of fixing up manually what a failed automatic
|
||||
@@ -327,36 +366,37 @@ GIT Glossary
|
||||
Synonym for <<def_object_name,object name>>.
|
||||
|
||||
[[def_shallow_repository]]shallow repository::
|
||||
A <<def_shallow_repository,shallow repository>> has an incomplete
|
||||
A shallow repository has an incomplete
|
||||
history some of whose commits have parents cauterized away (in other
|
||||
words, git is told to pretend that these commits do not have the
|
||||
parents, even though they are recorded in the <<def_commit_object,commit
|
||||
object>>). This is sometimes useful when you are interested only in the
|
||||
recent history of a project even though the real history recorded in the
|
||||
upstream is much larger. A <<def_shallow_repository,shallow repository>>
|
||||
upstream is much larger. A shallow repository
|
||||
is created by giving the `--depth` option to gitlink:git-clone[1], and
|
||||
its history can be later deepened with gitlink:git-fetch[1].
|
||||
|
||||
[[def_symref]]symref::
|
||||
Symbolic reference: instead of containing the <<def_SHA1,SHA1>> id
|
||||
itself, it is of the format 'ref: refs/some/thing' and when
|
||||
referenced, it recursively dereferences to this reference. 'HEAD' is a
|
||||
prime example of a <<def_symref,symref>>. Symbolic references are
|
||||
manipulated with the gitlink:git-symbolic-ref[1] command.
|
||||
Symbolic reference: instead of containing the <<def_SHA1,SHA1>>
|
||||
id itself, it is of the format 'ref: refs/some/thing' and when
|
||||
referenced, it recursively dereferences to this reference.
|
||||
'<<def_HEAD,HEAD>>' is a prime example of a symref. Symbolic
|
||||
references are manipulated with the gitlink:git-symbolic-ref[1]
|
||||
command.
|
||||
|
||||
[[def_tag]]tag::
|
||||
A <<def_ref,ref>> pointing to a <<def_tag,tag>> or
|
||||
A <<def_ref,ref>> pointing to a tag or
|
||||
<<def_commit_object,commit object>>. In contrast to a <<def_head,head>>,
|
||||
a tag is not changed by a <<def_commit,commit>>. Tags (not
|
||||
<<def_tag_object,tag objects>>) are stored in `$GIT_DIR/refs/tags/`. A
|
||||
git tag has nothing to do with a Lisp tag (which would be
|
||||
called an <<def_object_type,object type>> in git's context). A
|
||||
tag is most typically used to mark a particular point in the
|
||||
<<def_commit,commit>> ancestry <<def_chain,chain>>.
|
||||
commit ancestry <<def_chain,chain>>.
|
||||
|
||||
[[def_tag_object]]tag object::
|
||||
An <<def_object,object>> containing a <<def_ref,ref>> pointing to
|
||||
another <<def_object,object>>, which can contain a message just like a
|
||||
another object, which can contain a message just like a
|
||||
<<def_commit_object,commit object>>. It can also contain a (PGP)
|
||||
signature, in which case it is called a "signed <<def_tag_object,tag
|
||||
object>>".
|
||||
@@ -370,16 +410,16 @@ GIT Glossary
|
||||
|
||||
[[def_tracking_branch]]tracking branch::
|
||||
A regular git <<def_branch,branch>> that is used to follow changes from
|
||||
another <<def_repository,repository>>. A <<def_tracking_branch,tracking
|
||||
branch>> should not contain direct modifications or have local commits
|
||||
made to it. A <<def_tracking_branch,tracking branch>> can usually be
|
||||
another <<def_repository,repository>>. A tracking
|
||||
branch should not contain direct modifications or have local commits
|
||||
made to it. A tracking branch can usually be
|
||||
identified as the right-hand-side <<def_ref,ref>> in a Pull:
|
||||
<<def_refspec,refspec>>.
|
||||
|
||||
[[def_tree]]tree::
|
||||
Either a <<def_working_tree,working tree>>, or a <<def_tree_object,tree
|
||||
object>> together with the dependent blob and <<def_tree,tree>> objects
|
||||
(i.e. a stored representation of a <<def_working_tree,working tree>>).
|
||||
object>> together with the dependent blob and tree objects
|
||||
(i.e. a stored representation of a working tree).
|
||||
|
||||
[[def_tree_object]]tree object::
|
||||
An <<def_object,object>> containing a list of file names and modes along
|
||||
@@ -389,8 +429,7 @@ GIT Glossary
|
||||
[[def_tree-ish]]tree-ish::
|
||||
A <<def_ref,ref>> pointing to either a <<def_commit_object,commit
|
||||
object>>, a <<def_tree_object,tree object>>, or a <<def_tag_object,tag
|
||||
object>> pointing to a <<def_tag,tag>> or <<def_commit,commit>> or
|
||||
<<def_tree_object,tree object>>.
|
||||
object>> pointing to a tag or commit or tree object.
|
||||
|
||||
[[def_unmerged_index]]unmerged index::
|
||||
An <<def_index,index>> which contains unmerged
|
||||
@@ -401,5 +440,6 @@ GIT Glossary
|
||||
<<def_branch,branch>>, <<def_tag,tag>>, or any other reference.
|
||||
|
||||
[[def_working_tree]]working tree::
|
||||
The set of files and directories currently being worked on, i.e. you can
|
||||
work in your <<def_working_tree,working tree>> without using git at all.
|
||||
The tree of actual checked out files. The working tree is
|
||||
normally equal to the <<def_HEAD,HEAD>> plus any local changes
|
||||
that you have made but not yet committed.
|
||||
|
||||
@@ -90,6 +90,36 @@ parameter, and is invoked after a commit is made.
|
||||
This hook is meant primarily for notification, and cannot affect
|
||||
the outcome of `git-commit`.
|
||||
|
||||
[[pre-receive]]
|
||||
pre-receive
|
||||
-----------
|
||||
|
||||
This hook is invoked by `git-receive-pack` on the remote repository,
|
||||
which happens when a `git push` is done on a local repository.
|
||||
Just before starting to update refs on the remote repository, the
|
||||
pre-receive hook is invoked. Its exit status determines the success
|
||||
or failure of the update.
|
||||
|
||||
This hook executes once for the receive operation. It takes no
|
||||
arguments, but for each ref to be updated it receives on standard
|
||||
input a line of the format:
|
||||
|
||||
<old-value> SP <new-value> SP <ref-name> LF
|
||||
|
||||
where `<old-value>` is the old object name stored in the ref,
|
||||
`<new-value>` is the new object name to be stored in the ref and
|
||||
`<ref-name>` is the full name of the ref.
|
||||
When creating a new ref, `<old-value>` is 40 `0`.
|
||||
|
||||
If the hook exits with non-zero status, none of the refs will be
|
||||
updated. If the hook exits with zero, updating of individual refs can
|
||||
still be prevented by the <<update,'update'>> hook.
|
||||
|
||||
Both standard output and standard error output are forwarded to
|
||||
`git-send-pack` on the other end, so you can simply `echo` messages
|
||||
for the user.
|
||||
|
||||
[[update]]
|
||||
update
|
||||
------
|
||||
|
||||
@@ -108,7 +138,7 @@ three parameters:
|
||||
|
||||
A zero exit from the update hook allows the ref to be updated.
|
||||
Exiting with a non-zero status prevents `git-receive-pack`
|
||||
from updating the ref.
|
||||
from updating that ref.
|
||||
|
||||
This hook can be used to prevent 'forced' update on certain refs by
|
||||
making sure that the object name is a commit object that is a
|
||||
@@ -117,19 +147,52 @@ That is, to enforce a "fast forward only" policy.
|
||||
|
||||
It could also be used to log the old..new status. However, it
|
||||
does not know the entire set of branches, so it would end up
|
||||
firing one e-mail per ref when used naively, though.
|
||||
firing one e-mail per ref when used naively, though. The
|
||||
<<post-receive,'post-receive'>> hook is more suited to that.
|
||||
|
||||
Another use suggested on the mailing list is to use this hook to
|
||||
implement access control which is finer grained than the one
|
||||
based on filesystem group.
|
||||
|
||||
The standard output of this hook is sent to `stderr`, so if you
|
||||
want to report something to the `git-send-pack` on the other end,
|
||||
you can simply `echo` your messages.
|
||||
Both standard output and standard error output are forwarded to
|
||||
`git-send-pack` on the other end, so you can simply `echo` messages
|
||||
for the user.
|
||||
|
||||
The default 'update' hook, when enabled, demonstrates how to
|
||||
send out a notification e-mail.
|
||||
The default 'update' hook, when enabled--and with
|
||||
`hooks.allowunannotated` config option turned on--prevents
|
||||
unannotated tags to be pushed.
|
||||
|
||||
[[post-receive]]
|
||||
post-receive
|
||||
------------
|
||||
|
||||
This hook is invoked by `git-receive-pack` on the remote repository,
|
||||
which happens when a `git push` is done on a local repository.
|
||||
It executes on the remote repository once after all the refs have
|
||||
been updated.
|
||||
|
||||
This hook executes once for the receive operation. It takes no
|
||||
arguments, but gets the same information as the
|
||||
<<pre-receive,'pre-receive'>>
|
||||
hook does on its standard input.
|
||||
|
||||
This hook does not affect the outcome of `git-receive-pack`, as it
|
||||
is called after the real work is done.
|
||||
|
||||
This supersedes the <<post-update,'post-update'>> hook in that it get's
|
||||
both old and new values of all the refs in addition to their
|
||||
names.
|
||||
|
||||
Both standard output and standard error output are forwarded to
|
||||
`git-send-pack` on the other end, so you can simply `echo` messages
|
||||
for the user.
|
||||
|
||||
The default 'post-receive' hook is empty, but there is
|
||||
a sample script `post-receive-email` provided in the `contrib/hooks`
|
||||
directory in git distribution, which implements sending commit
|
||||
emails.
|
||||
|
||||
[[post-update]]
|
||||
post-update
|
||||
-----------
|
||||
|
||||
@@ -146,7 +209,10 @@ the outcome of `git-receive-pack`.
|
||||
|
||||
The 'post-update' hook can tell what are the heads that were pushed,
|
||||
but it does not know what their original and updated values are,
|
||||
so it is a poor place to do log old..new.
|
||||
so it is a poor place to do log old..new. The
|
||||
<<post-receive,'post-receive'>> hook does get both original and
|
||||
updated values of the refs. You might consider it instead if you need
|
||||
them.
|
||||
|
||||
When enabled, the default 'post-update' hook runs
|
||||
`git-update-server-info` to keep the information used by dumb
|
||||
@@ -154,6 +220,6 @@ transports (e.g., HTTP) up-to-date. If you are publishing
|
||||
a git repository that is accessible via HTTP, you should
|
||||
probably enable this hook.
|
||||
|
||||
The standard output of this hook is sent to `/dev/null`; if you
|
||||
want to report something to the `git-send-pack` on the other end,
|
||||
you can redirect your output to your `stderr`.
|
||||
Both standard output and standard error output are forwarded to
|
||||
`git-send-pack` on the other end, so you can simply `echo` messages
|
||||
for the user.
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
From: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Subject: Re: Question about fsck-objects output
|
||||
Date: Thu, 25 Jan 2007 12:01:06 -0800 (PST)
|
||||
Message-ID: <Pine.LNX.4.64.0701251144290.25027@woody.linux-foundation.org>
|
||||
Archived-At: <http://permalink.gmane.org/gmane.comp.version-control.git/37754>
|
||||
Abstract: Linus describes what dangling objects are, when they
|
||||
are left behind, and how to view their relationship with branch
|
||||
heads in gitk
|
||||
|
||||
On Thu, 25 Jan 2007, Larry Streepy wrote:
|
||||
|
||||
> Sorry to ask such a basic question, but I can't quite decipher the output of
|
||||
> fsck-objects. When I run it, I get this:
|
||||
>
|
||||
> git fsck-objects
|
||||
> dangling commit 2213f6d4dd39ca8baebd0427723723e63208521b
|
||||
> dangling commit f0d4e00196bd5ee54463e9ea7a0f0e8303da767f
|
||||
> dangling blob 6a6d0b01b3e96d49a8f2c7addd4ef8c3bd1f5761
|
||||
>
|
||||
>
|
||||
> Even after a "repack -a -d" they still exist. The man page has a short
|
||||
> explanation, but, at least for me, it wasn't fully enlightening. :-)
|
||||
>
|
||||
> The man page says that dangling commits could be "root" commits, but since my
|
||||
> repo started as a clone of another repo, I don't see how I could have any root
|
||||
> commits. Also, the page doesn't really describe what a dangling blob is.
|
||||
>
|
||||
> So, can someone explain what these artifacts are and if they are a problem
|
||||
> that I should be worried about?
|
||||
|
||||
The most common situation is that you've rebased a branch (or you have
|
||||
pulled from somebody else who rebased a branch, like the "pu" branch in
|
||||
the git.git archive itself).
|
||||
|
||||
What happens is that the old head of the original branch still exists, as
|
||||
does obviously everything it pointed to. The branch pointer itself just
|
||||
doesn't, since you replaced it with another one.
|
||||
|
||||
However, there are certainly other situations too that cause dangling
|
||||
objects. For example, the "dangling blob" situation you have tends to be
|
||||
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 not being pointed to by any commit/tree, so
|
||||
it's now a dangling blob object.
|
||||
|
||||
Similarly, when the "recursive" merge strategy runs, and finds that there
|
||||
are criss-cross merges and thus more than one merge base (which is fairly
|
||||
unusual, but it does happen), it will generate one temporary midway tree
|
||||
(or possibly even more, if you had lots of criss-crossing merges and
|
||||
more than two merge bases) as a temporary internal merge base, and again,
|
||||
those are real objects, but the end result will not end up pointing to
|
||||
them, so they end up "dangling" in your repository.
|
||||
|
||||
Generally, dangling objects aren't anything to worry about. They can even
|
||||
be very useful: if you screw something up, the dangling objects can be how
|
||||
you recover your old tree (say, you did a rebase, and realized that you
|
||||
really didn't want to - you can look at what dangling objects you have,
|
||||
and decide to reset your head to some old dangling state).
|
||||
|
||||
For commits, the most useful thing to do with dangling objects tends to be
|
||||
to do a simple
|
||||
|
||||
gitk <dangling-commit-sha-goes-here> --not --all
|
||||
|
||||
which means exactly what it sounds like: it says that you want to see the
|
||||
commit history that is described by the dangling commit(s), but you do NOT
|
||||
want to see the history that is described by all your branches and tags
|
||||
(which are the things you normally reach). That basically shows you in a
|
||||
nice way what the danglign commit was (and notice that it might not be
|
||||
just one commit: we only report the "tip of the line" as being dangling,
|
||||
but there might be a whole deep and complex commit history that has gotten
|
||||
dropped - rebasing will do that).
|
||||
|
||||
For blobs and trees, you can't do the same, but you can examine them. You
|
||||
can just do
|
||||
|
||||
git show <dangling-blob/tree-sha-goes-here>
|
||||
|
||||
to show what the contents of the blob were (or, for a tree, basically what
|
||||
the "ls" for that directory was), and that may give you some idea of what
|
||||
the operation was that left that dangling object.
|
||||
|
||||
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, leaving _some_
|
||||
of the new objects in the object database, but just dangling and useless.
|
||||
|
||||
Anyway, once you are sure that you're not interested in any dangling
|
||||
state, you can just prune all unreachable objects:
|
||||
|
||||
git prune
|
||||
|
||||
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-objects" itself, btw - but since
|
||||
git-fsck-objects never actually *changes* the repository, it just reports
|
||||
on what it found, git-fsck-objects 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
|
||||
repository is a *BAD* idea).
|
||||
|
||||
Linus
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
From: Linus Torvalds <torvalds () osdl ! org>
|
||||
To: git@vger.kernel.org
|
||||
Date: 2005-11-08 1:31:34
|
||||
Subject: Real-life kernel debugging scenario
|
||||
Abstract: Short-n-sweet, Linus tells us how to leverage `git-bisect` to perform
|
||||
bug isolation on a repository where "good" and "bad" revisions are known
|
||||
in order to identify a suspect commit.
|
||||
|
||||
|
||||
How To Use git-bisect To Isolate a Bogus Commit
|
||||
===============================================
|
||||
|
||||
The way to use "git bisect" couldn't be easier.
|
||||
|
||||
Figure out what the oldest bad state you know about is (that's usually the
|
||||
head of "master", since that's what you just tried to boot and failed at).
|
||||
Also, figure out the most recent known-good commit (usually the _previous_
|
||||
kernel you ran: and if you've only done a single "pull" in between, it
|
||||
will be ORIG_HEAD).
|
||||
|
||||
Then do
|
||||
|
||||
git bisect start
|
||||
git bisect bad master <- mark "master" as the bad state
|
||||
git bisect good ORIG_HEAD <- mark ORIG_HEAD as good (or
|
||||
whatever other known-good
|
||||
thing you booted last)
|
||||
|
||||
and at this point "git bisect" will churn for a while, and tell you what
|
||||
the mid-point between those two commits are, and check that state out as
|
||||
the head of the new "bisect" branch.
|
||||
|
||||
Compile and reboot.
|
||||
|
||||
If it's good, just do
|
||||
|
||||
git bisect good <- mark current head as good
|
||||
|
||||
otherwise, reboot into a good kernel instead, and do (surprise surprise,
|
||||
git really is very intuitive):
|
||||
|
||||
git bisect bad <- mark current head as bad
|
||||
|
||||
and whatever you do, git will select a new half-way point. Do this for a
|
||||
while, until git tells you exactly which commit was the first bad commit.
|
||||
That's your culprit.
|
||||
|
||||
It really works wonderfully well, except for the case where there was
|
||||
_another_ commit that broke something in between, like introduced some
|
||||
stupid compile error. In that case you should not mark that commit good or
|
||||
bad: you should try to find another commit close-by, and do a "git reset
|
||||
--hard <newcommit>" to try out _that_ commit instead, and then test that
|
||||
instead (and mark it good or bad).
|
||||
|
||||
You can do "git bisect visualize" while you do all this to see what's
|
||||
going on by starting up gitk on the bisection range.
|
||||
|
||||
Finally, once you've figured out exactly which commit was bad, you can
|
||||
then go back to the master branch, and try reverting just that commit:
|
||||
|
||||
git checkout master
|
||||
git revert <bad-commit-id>
|
||||
|
||||
to verify that the top-of-kernel works with that single commit reverted.
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
Date: Fri, 12 Aug 2005 22:39:48 -0700 (PDT)
|
||||
From: Linus Torvalds <torvalds@osdl.org>
|
||||
To: Dave Jones <davej@redhat.com>
|
||||
cc: git@vger.kernel.org
|
||||
Subject: Re: Fwd: Re: git checkout -f branch doesn't remove extra files
|
||||
Abstract: In this article, Linus talks about building a tarball,
|
||||
incremental patch, and ChangeLog, given a base release and two
|
||||
rc releases, following the convention of giving the patch from
|
||||
the base release and the latest rc, with ChangeLog between the
|
||||
last rc and the latest rc.
|
||||
|
||||
On Sat, 13 Aug 2005, Dave Jones wrote:
|
||||
>
|
||||
> > Git actually has a _lot_ of nifty tools. I didn't realize that people
|
||||
> > didn't know about such basic stuff as "git-tar-tree" and "git-ls-files".
|
||||
>
|
||||
> Maybe its because things are moving so fast :) Or maybe I just wasn't
|
||||
> paying attention on that day. (I even read the git changes via RSS,
|
||||
> so I should have no excuse).
|
||||
|
||||
Well, git-tar-tree has been there since late April - it's actually one of
|
||||
those really early commands. I'm pretty sure the RSS feed came later ;)
|
||||
|
||||
I use it all the time in doing releases, it's a lot faster than creating a
|
||||
tar tree by reading the filesystem (even if you don't have to check things
|
||||
out). A hidden pearl.
|
||||
|
||||
This is my crappy "release-script":
|
||||
|
||||
[torvalds@g5 ~]$ cat bin/release-script
|
||||
#!/bin/sh
|
||||
stable="$1"
|
||||
last="$2"
|
||||
new="$3"
|
||||
echo "# git-tag v$new"
|
||||
echo "git-tar-tree v$new linux-$new | gzip -9 > ../linux-$new.tar.gz"
|
||||
echo "git-diff-tree -p v$stable v$new | gzip -9 > ../patch-$new.gz"
|
||||
echo "git-rev-list --pretty v$new ^v$last > ../ChangeLog-$new"
|
||||
echo "git-rev-list --pretty=short v$new ^v$last | git-shortlog > ../ShortLog"
|
||||
echo "git-diff-tree -p v$last v$new | git-apply --stat > ../diffstat-$new"
|
||||
|
||||
and when I want to do a new kernel release I literally first tag it, and
|
||||
then do
|
||||
|
||||
release-script 2.6.12 2.6.13-rc6 2.6.13-rc7
|
||||
|
||||
and check that things look sane, and then just cut-and-paste the commands.
|
||||
|
||||
Yeah, it's stupid.
|
||||
|
||||
Linus
|
||||
|
||||
@@ -1,296 +0,0 @@
|
||||
Date: Mon, 15 Aug 2005 12:17:41 -0700
|
||||
From: tony.luck@intel.com
|
||||
Subject: Some tutorial text (was git/cogito workshop/bof at linuxconf au?)
|
||||
Abstract: In this article, Tony Luck discusses how he uses GIT
|
||||
as a Linux subsystem maintainer.
|
||||
|
||||
Here's something that I've been putting together on how I'm using
|
||||
GIT as a Linux subsystem maintainer.
|
||||
|
||||
-Tony
|
||||
|
||||
Last updated w.r.t. GIT 1.1
|
||||
|
||||
Linux subsystem maintenance using GIT
|
||||
-------------------------------------
|
||||
|
||||
My requirements here are to be able to create two public trees:
|
||||
|
||||
1) A "test" tree into which patches are initially placed so that they
|
||||
can get some exposure when integrated with other ongoing development.
|
||||
This tree is available to Andrew for pulling into -mm whenever he wants.
|
||||
|
||||
2) A "release" tree into which tested patches are moved for final
|
||||
sanity checking, and as a vehicle to send them upstream to Linus
|
||||
(by sending him a "please pull" request.)
|
||||
|
||||
Note that the period of time that each patch spends in the "test" tree
|
||||
is dependent on the complexity of the change. Since GIT does not support
|
||||
cherry picking, it is not practical to simply apply all patches to the
|
||||
test tree and then pull to the release tree as that would leave trivial
|
||||
patches blocked in the test tree waiting for complex changes to accumulate
|
||||
enough test time to graduate.
|
||||
|
||||
Back in the BitKeeper days I achieved this by creating small forests of
|
||||
temporary trees, one tree for each logical grouping of patches, and then
|
||||
pulling changes from these trees first to the test tree, and then to the
|
||||
release tree. At first I replicated this in GIT, but then I realised
|
||||
that I could so this far more efficiently using branches inside a single
|
||||
GIT repository.
|
||||
|
||||
So here is the step-by-step guide how this all works for me.
|
||||
|
||||
First create your work tree by cloning Linus's public tree:
|
||||
|
||||
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
|
||||
|
||||
Change directory into the cloned tree you just created
|
||||
|
||||
$ cd work
|
||||
|
||||
Set up a remotes file so that you can fetch the latest from Linus' master
|
||||
branch into a local branch named "linus":
|
||||
|
||||
$ cat > .git/remotes/linus
|
||||
URL: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
|
||||
Pull: master:linus
|
||||
^D
|
||||
|
||||
and create the linus branch:
|
||||
|
||||
$ git branch linus
|
||||
|
||||
The "linus" branch will be used to track the upstream kernel. To update it,
|
||||
you simply run:
|
||||
|
||||
$ git fetch linus
|
||||
|
||||
you can do this frequently (and it should be safe to do so with pending
|
||||
work in your tree, but perhaps not if you are in mid-merge).
|
||||
|
||||
If you need to keep track of other public trees, you can add remote branches
|
||||
for them too:
|
||||
|
||||
$ git branch another
|
||||
$ cat > .git/remotes/another
|
||||
URL: ... insert URL here ...
|
||||
Pull: name-of-branch-in-this-remote-tree:another
|
||||
^D
|
||||
|
||||
and run:
|
||||
|
||||
$ git fetch another
|
||||
|
||||
Now create the branches in which you are going to work, these start
|
||||
out at the current tip of the linus branch.
|
||||
|
||||
$ git branch test linus
|
||||
$ git branch release linus
|
||||
|
||||
These can be easily kept up to date by merging from the "linus" branch:
|
||||
|
||||
$ git checkout test && git merge "Auto-update from upstream" test linus
|
||||
$ git checkout release && git merge "Auto-update from upstream" release linus
|
||||
|
||||
Important note! If you have any local changes in these branches, then
|
||||
this merge will create a commit object in the history (with no local
|
||||
changes git will simply do a "Fast forward" merge). Many people dislike
|
||||
the "noise" that this creates in the Linux history, so you should avoid
|
||||
doing this capriciously in the "release" branch, as these noisy commits
|
||||
will become part of the permanent history when you ask Linus to pull
|
||||
from the release branch.
|
||||
|
||||
Set up so that you can push upstream to your public tree (you need to
|
||||
log-in to the remote system and create an empty tree there before the
|
||||
first push).
|
||||
|
||||
$ cat > .git/remotes/mytree
|
||||
URL: master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
|
||||
Push: release
|
||||
Push: test
|
||||
^D
|
||||
|
||||
and the push both the test and release trees using:
|
||||
|
||||
$ git push mytree
|
||||
|
||||
or push just one of the test and release branches using:
|
||||
|
||||
$ git push mytree test
|
||||
or
|
||||
$ git push mytree release
|
||||
|
||||
Now to apply some patches from the community. Think of a short
|
||||
snappy name for a branch to hold this patch (or related group of
|
||||
patches), and create a new branch from the current tip of the
|
||||
linus branch:
|
||||
|
||||
$ git checkout -b speed-up-spinlocks linus
|
||||
|
||||
Now you apply the patch(es), run some tests, and commit the change(s). If
|
||||
the patch is a multi-part series, then you should apply each as a separate
|
||||
commit to this branch.
|
||||
|
||||
$ ... patch ... test ... commit [ ... patch ... test ... commit ]*
|
||||
|
||||
When you are happy with the state of this change, you can pull it into the
|
||||
"test" branch in preparation to make it public:
|
||||
|
||||
$ git checkout test && git merge "Pull speed-up-spinlock changes" test speed-up-spinlocks
|
||||
|
||||
It is unlikely that you would have any conflicts here ... but you might if you
|
||||
spent a while on this step and had also pulled new versions from upstream.
|
||||
|
||||
Some time later when enough time has passed and testing done, you can pull the
|
||||
same branch into the "release" tree ready to go upstream. This is where you
|
||||
see the value of keeping each patch (or patch series) in its own branch. It
|
||||
means that the patches can be moved into the "release" tree in any order.
|
||||
|
||||
$ git checkout release && git merge "Pull speed-up-spinlock changes" release speed-up-spinlocks
|
||||
|
||||
After a while, you will have a number of branches, and despite the
|
||||
well chosen names you picked for each of them, you may forget what
|
||||
they are for, or what status they are in. To get a reminder of what
|
||||
changes are in a specific branch, use:
|
||||
|
||||
$ git-whatchanged branchname ^linus | git-shortlog
|
||||
|
||||
To see whether it has already been merged into the test or release branches
|
||||
use:
|
||||
|
||||
$ git-rev-list branchname ^test
|
||||
or
|
||||
$ git-rev-list branchname ^release
|
||||
|
||||
[If this branch has not yet been merged you will see a set of SHA1 values
|
||||
for the commits, if it has been merged, then there will be no output]
|
||||
|
||||
Once a patch completes the great cycle (moving from test to release, then
|
||||
pulled by Linus, and finally coming back into your local "linus" branch)
|
||||
the branch for this change is no longer needed. You detect this when the
|
||||
output from:
|
||||
|
||||
$ git-rev-list branchname ^linus
|
||||
|
||||
is empty. At this point the branch can be deleted:
|
||||
|
||||
$ git branch -d branchname
|
||||
|
||||
Some changes are so trivial that it is not necessary to create a separate
|
||||
branch and then merge into each of the test and release branches. For
|
||||
these changes, just apply directly to the "release" branch, and then
|
||||
merge that into the "test" branch.
|
||||
|
||||
To create diffstat and shortlog summaries of changes to include in a "please
|
||||
pull" request to Linus you can use:
|
||||
|
||||
$ git-whatchanged -p release ^linus | diffstat -p1
|
||||
and
|
||||
$ git-whatchanged release ^linus | git-shortlog
|
||||
|
||||
|
||||
Here are some of the scripts that I use to simplify all this even further.
|
||||
|
||||
==== update script ====
|
||||
# Update a branch in my GIT tree. If the branch to be updated
|
||||
# is "linus", then pull from kernel.org. Otherwise merge local
|
||||
# linus branch into test|release branch
|
||||
|
||||
case "$1" in
|
||||
test|release)
|
||||
git checkout $1 && git merge "Auto-update from upstream" $1 linus
|
||||
;;
|
||||
linus)
|
||||
before=$(cat .git/refs/heads/linus)
|
||||
git fetch linus
|
||||
after=$(cat .git/refs/heads/linus)
|
||||
if [ $before != $after ]
|
||||
then
|
||||
git-whatchanged $after ^$before | git-shortlog
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 linus|test|release" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
==== merge script ====
|
||||
# Merge a branch into either the test or release branch
|
||||
|
||||
pname=$0
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "Usage: $pname branch test|release" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ ! -f .git/refs/heads/"$1" ]
|
||||
then
|
||||
echo "Can't see branch <$1>" 1>&2
|
||||
usage
|
||||
fi
|
||||
|
||||
case "$2" in
|
||||
test|release)
|
||||
if [ $(git-rev-list $1 ^$2 | wc -c) -eq 0 ]
|
||||
then
|
||||
echo $1 already merged into $2 1>&2
|
||||
exit 1
|
||||
fi
|
||||
git checkout $2 && git merge "Pull $1 into $2 branch" $2 $1
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
==== status script ====
|
||||
# report on status of my ia64 GIT tree
|
||||
|
||||
gb=$(tput setab 2)
|
||||
rb=$(tput setab 1)
|
||||
restore=$(tput setab 9)
|
||||
|
||||
if [ `git-rev-list release ^test | wc -c` -gt 0 ]
|
||||
then
|
||||
echo $rb Warning: commits in release that are not in test $restore
|
||||
git-whatchanged release ^test
|
||||
fi
|
||||
|
||||
for branch in `ls .git/refs/heads`
|
||||
do
|
||||
if [ $branch = linus -o $branch = test -o $branch = release ]
|
||||
then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo -n $gb ======= $branch ====== $restore " "
|
||||
status=
|
||||
for ref in test release linus
|
||||
do
|
||||
if [ `git-rev-list $branch ^$ref | wc -c` -gt 0 ]
|
||||
then
|
||||
status=$status${ref:0:1}
|
||||
fi
|
||||
done
|
||||
case $status in
|
||||
trl)
|
||||
echo $rb Need to pull into test $restore
|
||||
;;
|
||||
rl)
|
||||
echo "In test"
|
||||
;;
|
||||
l)
|
||||
echo "Waiting for linus"
|
||||
;;
|
||||
"")
|
||||
echo $rb All done $restore
|
||||
;;
|
||||
*)
|
||||
echo $rb "<$status>" $restore
|
||||
;;
|
||||
esac
|
||||
git-whatchanged $branch ^linus | git-shortlog
|
||||
done
|
||||
@@ -1,31 +1,32 @@
|
||||
--pretty[='<format>']::
|
||||
PRETTY FORMATS
|
||||
--------------
|
||||
|
||||
Pretty-prints the details of a commit. `--pretty`
|
||||
without an explicit `=<format>` defaults to 'medium'.
|
||||
If the commit is a merge, and if the pretty-format
|
||||
is not 'oneline', 'email' or 'raw', an additional line is
|
||||
inserted before the 'Author:' line. This line begins with
|
||||
"Merge: " and the sha1s of ancestral commits are printed,
|
||||
separated by spaces. Note that the listed commits may not
|
||||
necessarily be the list of the *direct* parent commits if you
|
||||
have limited your view of history: for example, if you are
|
||||
only interested in changes related to a certain directory or
|
||||
file. Here are some additional details for each format:
|
||||
If the commit is a merge, and if the pretty-format
|
||||
is not 'oneline', 'email' or 'raw', an additional line is
|
||||
inserted before the 'Author:' line. This line begins with
|
||||
"Merge: " and the sha1s of ancestral commits are printed,
|
||||
separated by spaces. Note that the listed commits may not
|
||||
necessarily be the list of the *direct* parent commits if you
|
||||
have limited your view of history: for example, if you are
|
||||
only interested in changes related to a certain directory or
|
||||
file.
|
||||
|
||||
* 'oneline'
|
||||
Here are some additional details for each format:
|
||||
|
||||
* 'oneline'
|
||||
|
||||
<sha1> <title line>
|
||||
+
|
||||
This is designed to be as compact as possible.
|
||||
|
||||
* 'short'
|
||||
* 'short'
|
||||
|
||||
commit <sha1>
|
||||
Author: <author>
|
||||
|
||||
<title line>
|
||||
|
||||
* 'medium'
|
||||
* 'medium'
|
||||
|
||||
commit <sha1>
|
||||
Author: <author>
|
||||
@@ -35,7 +36,7 @@ This is designed to be as compact as possible.
|
||||
|
||||
<full commit message>
|
||||
|
||||
* 'full'
|
||||
* 'full'
|
||||
|
||||
commit <sha1>
|
||||
Author: <author>
|
||||
@@ -45,7 +46,7 @@ This is designed to be as compact as possible.
|
||||
|
||||
<full commit message>
|
||||
|
||||
* 'fuller'
|
||||
* 'fuller'
|
||||
|
||||
commit <sha1>
|
||||
Author: <author>
|
||||
@@ -57,18 +58,16 @@ This is designed to be as compact as possible.
|
||||
|
||||
<full commit message>
|
||||
|
||||
|
||||
* 'email'
|
||||
* 'email'
|
||||
|
||||
From <sha1> <date>
|
||||
From: <author>
|
||||
Date: <date & time>
|
||||
Subject: [PATCH] <title line>
|
||||
|
||||
full commit message>
|
||||
<full commit message>
|
||||
|
||||
|
||||
* 'raw'
|
||||
* 'raw'
|
||||
+
|
||||
The 'raw' format shows the entire commit exactly as
|
||||
stored in the commit object. Notably, the SHA1s are
|
||||
@@ -77,19 +76,22 @@ displayed in full, regardless of whether --abbrev or
|
||||
true parent commits, without taking grafts nor history
|
||||
simplification into account.
|
||||
|
||||
* 'format:'
|
||||
* 'format:'
|
||||
+
|
||||
The 'format:' format allows you to specify which information
|
||||
you want to show. It works a little bit like printf format,
|
||||
with the notable exception that you get a newline with '%n'
|
||||
instead of '\n'.
|
||||
|
||||
E.g, 'format:"The author of %h was %an, %ar%nThe title was >>%s<<"'
|
||||
+
|
||||
E.g, 'format:"The author of %h was %an, %ar%nThe title was >>%s<<%n"'
|
||||
would show something like this:
|
||||
|
||||
+
|
||||
-------
|
||||
The author of fe6e0ee was Junio C Hamano, 23 hours ago
|
||||
The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<
|
||||
|
||||
--------
|
||||
+
|
||||
The placeholders are:
|
||||
|
||||
- '%H': commit hash
|
||||
@@ -120,11 +122,3 @@ The placeholders are:
|
||||
- '%m': left, right or boundary mark
|
||||
- '%n': newline
|
||||
|
||||
|
||||
--encoding[=<encoding>]::
|
||||
The commit objects record the encoding used for the log message
|
||||
in their encoding header; this option can be used to tell the
|
||||
command to re-code the commit log message in the encoding
|
||||
preferred by the user. For non plumbing commands this
|
||||
defaults to UTF-8.
|
||||
|
||||
|
||||
14
Documentation/pretty-options.txt
Normal file
14
Documentation/pretty-options.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
--pretty[='<format>']::
|
||||
|
||||
Pretty print the contents of the commit logs in a given format,
|
||||
where '<format>' can be one of 'oneline', 'short', 'medium',
|
||||
'full', 'fuller', 'email', 'raw' and 'format:<string>'.
|
||||
When left out the format default to 'medium'.
|
||||
|
||||
--encoding[=<encoding>]::
|
||||
The commit objects record the encoding used for the log message
|
||||
in their encoding header; this option can be used to tell the
|
||||
command to re-code the commit log message in the encoding
|
||||
preferred by the user. For non plumbing commands this
|
||||
defaults to UTF-8.
|
||||
|
||||
@@ -391,6 +391,9 @@ with the commands mentioned in link:everyday.html[Everyday git]. You
|
||||
should be able to find any unknown jargon in the
|
||||
link:glossary.html[Glossary].
|
||||
|
||||
The link:user-manual.html[Git User's Manual] provides a more
|
||||
comprehensive introduction to git.
|
||||
|
||||
The link:cvs-migration.html[CVS migration] document explains how to
|
||||
import a CVS repository into git, and shows how to use git in a
|
||||
CVS-like way.
|
||||
|
||||
@@ -4,6 +4,10 @@ A tutorial introduction to git (for version 1.5.1 or newer)
|
||||
This tutorial explains how to import a new project into git, make
|
||||
changes to it, and share changes with other developers.
|
||||
|
||||
If you are instead primarily interested in using git to fetch a project,
|
||||
for example, to test the latest version, you may prefer to start with
|
||||
the first two chapters of link:user-manual.html[The Git User's Manual].
|
||||
|
||||
First, note that you can get documentation for a command such as "git
|
||||
diff" with:
|
||||
|
||||
@@ -40,42 +44,67 @@ Initialized empty Git repository in .git/
|
||||
------------------------------------------------
|
||||
|
||||
You've now initialized the working directory--you may notice a new
|
||||
directory created, named ".git". Tell git that you want it to track
|
||||
every file under the current directory (note the '.') with:
|
||||
directory created, named ".git".
|
||||
|
||||
Next, tell git to take a snapshot of the contents of all files under the
|
||||
current directory (note the '.'), with gitlink:git-add[1]:
|
||||
|
||||
------------------------------------------------
|
||||
$ git add .
|
||||
------------------------------------------------
|
||||
|
||||
Finally,
|
||||
This snapshot is now stored in a temporary staging area which git calls
|
||||
the "index". You can permanently store the contents of the index in the
|
||||
repository with gitlink:git-commit[1]:
|
||||
|
||||
------------------------------------------------
|
||||
$ git commit
|
||||
------------------------------------------------
|
||||
|
||||
will prompt you for a commit message, then record the current state
|
||||
of all the files to the repository.
|
||||
This will prompt you for a commit message. You've now stored the first
|
||||
version of your project in git.
|
||||
|
||||
Making changes
|
||||
--------------
|
||||
|
||||
Try modifying some files, then run
|
||||
|
||||
------------------------------------------------
|
||||
$ git diff
|
||||
------------------------------------------------
|
||||
|
||||
to review your changes. When you're done, tell git that you
|
||||
want the updated contents of these files in the commit and then
|
||||
make a commit, like this:
|
||||
Modify some files, then add their updated contents to the index:
|
||||
|
||||
------------------------------------------------
|
||||
$ git add file1 file2 file3
|
||||
------------------------------------------------
|
||||
|
||||
You are now ready to commit. You can see what is about to be committed
|
||||
using gitlink:git-diff[1] with the --cached option:
|
||||
|
||||
------------------------------------------------
|
||||
$ git diff --cached
|
||||
------------------------------------------------
|
||||
|
||||
(Without --cached, gitlink:git-diff[1] will show you any changes that
|
||||
you've made but not yet added to the index.) You can also get a brief
|
||||
summary of the situation with gitlink:git-status[1]:
|
||||
|
||||
------------------------------------------------
|
||||
$ git status
|
||||
# On branch master
|
||||
# Changes to be committed:
|
||||
# (use "git reset HEAD <file>..." to unstage)
|
||||
#
|
||||
# modified: file1
|
||||
# modified: file2
|
||||
# modified: file3
|
||||
#
|
||||
------------------------------------------------
|
||||
|
||||
If you need to make any further adjustments, do so now, and then add any
|
||||
newly modified content to the index. Finally, commit your changes with:
|
||||
|
||||
------------------------------------------------
|
||||
$ git commit
|
||||
------------------------------------------------
|
||||
|
||||
This will again prompt your for a message describing the change, and then
|
||||
record the new versions of the files you listed.
|
||||
record a new version of the project.
|
||||
|
||||
Alternatively, instead of running `git add` beforehand, you can use
|
||||
|
||||
@@ -83,7 +112,8 @@ Alternatively, instead of running `git add` beforehand, you can use
|
||||
$ git commit -a
|
||||
------------------------------------------------
|
||||
|
||||
which will automatically notice modified (but not new) files.
|
||||
which will automatically notice any modified (but not new) files, add
|
||||
them to the index, and commit, all in one step.
|
||||
|
||||
A note on commit messages: Though not required, it's a good idea to
|
||||
begin the commit message with a single short (less than 50 character)
|
||||
@@ -92,45 +122,15 @@ thorough description. Tools that turn commits into email, for
|
||||
example, use the first line on the Subject: line and the rest of the
|
||||
commit in the body.
|
||||
|
||||
|
||||
Git tracks content not files
|
||||
----------------------------
|
||||
|
||||
With git you have to explicitly "add" all the changed _content_ you
|
||||
want to commit together. This can be done in a few different ways:
|
||||
|
||||
1) By using 'git add <file_spec>...'
|
||||
|
||||
This can be performed multiple times before a commit. Note that this
|
||||
is not only for adding new files. Even modified files must be
|
||||
added to the set of changes about to be committed. The "git status"
|
||||
command gives you a summary of what is included so far for the
|
||||
next commit. When done you should use the 'git commit' command to
|
||||
make it real.
|
||||
|
||||
Note: don't forget to 'add' a file again if you modified it after the
|
||||
first 'add' and before 'commit'. Otherwise only the previous added
|
||||
state of that file will be committed. This is because git tracks
|
||||
content, so what you're really 'adding' to the commit is the *content*
|
||||
of the file in the state it is in when you 'add' it.
|
||||
|
||||
2) By using 'git commit -a' directly
|
||||
|
||||
This is a quick way to automatically 'add' the content from all files
|
||||
that were modified since the previous commit, and perform the actual
|
||||
commit without having to separately 'add' them beforehand. This will
|
||||
not add content from new files i.e. files that were never added before.
|
||||
Those files still have to be added explicitly before performing a
|
||||
commit.
|
||||
|
||||
But here's a twist. If you do 'git commit <file1> <file2> ...' then only
|
||||
the changes belonging to those explicitly specified files will be
|
||||
committed, entirely bypassing the current "added" changes. Those "added"
|
||||
changes will still remain available for a subsequent commit though.
|
||||
|
||||
However, for normal usage you only have to remember 'git add' + 'git commit'
|
||||
and/or 'git commit -a'.
|
||||
|
||||
Many revision control systems provide an "add" command that tells the
|
||||
system to start tracking changes to a new file. Git's "add" command
|
||||
does something simpler and more powerful: `git add` is used both for new
|
||||
and newly modified files, and in both cases it takes a snapshot of the
|
||||
given files and stages that content in the index, ready for inclusion in
|
||||
the next commit.
|
||||
|
||||
Viewing the changelog
|
||||
---------------------
|
||||
@@ -564,7 +564,7 @@ link:tutorial-2.html[Part two of this tutorial] explains the object
|
||||
database, the index file, and a few other odds and ends that you'll
|
||||
need to make the most of git.
|
||||
|
||||
If you don't want to consider with that right away, a few other
|
||||
If you don't want to continue with that right away, a few other
|
||||
digressions that may be interesting at this point are:
|
||||
|
||||
* gitlink:git-format-patch[1], gitlink:git-am[1]: These convert
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v1.5.2-rc3.GIT
|
||||
DEF_VER=v1.5.2.GIT
|
||||
|
||||
LF='
|
||||
'
|
||||
|
||||
2
Makefile
2
Makefile
@@ -319,7 +319,7 @@ LIB_OBJS = \
|
||||
write_or_die.o trace.o list-objects.o grep.o match-trees.o \
|
||||
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
|
||||
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
|
||||
convert.o attr.o decorate.o progress.o mailmap.o
|
||||
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o
|
||||
|
||||
BUILTIN_OBJS = \
|
||||
builtin-add.o \
|
||||
|
||||
@@ -82,12 +82,13 @@ static void strbuf_append_string(struct strbuf *sb, const char *s)
|
||||
{
|
||||
int slen = strlen(s);
|
||||
int total = sb->len + slen;
|
||||
if (total > sb->alloc) {
|
||||
sb->buf = xrealloc(sb->buf, total);
|
||||
sb->alloc = total;
|
||||
if (total + 1 > sb->alloc) {
|
||||
sb->buf = xrealloc(sb->buf, total + 1);
|
||||
sb->alloc = total + 1;
|
||||
}
|
||||
memcpy(sb->buf + sb->len, s, slen);
|
||||
sb->len = total;
|
||||
sb->buf[total] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -166,7 +167,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
|
||||
} else {
|
||||
if (verbose)
|
||||
fprintf(stderr, "%.*s\n", path->len, path->buf);
|
||||
if (S_ISDIR(mode)) {
|
||||
if (S_ISDIR(mode) || S_ISDIRLNK(mode)) {
|
||||
*header.typeflag = TYPEFLAG_DIR;
|
||||
mode = (mode | 0777) & ~tar_umask;
|
||||
} else if (S_ISLNK(mode)) {
|
||||
@@ -270,20 +271,21 @@ static int write_tar_entry(const unsigned char *sha1,
|
||||
path.alloc = PATH_MAX;
|
||||
path.len = path.eof = 0;
|
||||
}
|
||||
if (path.alloc < baselen + filenamelen) {
|
||||
if (path.alloc < baselen + filenamelen + 1) {
|
||||
free(path.buf);
|
||||
path.buf = xmalloc(baselen + filenamelen);
|
||||
path.alloc = baselen + filenamelen;
|
||||
path.buf = xmalloc(baselen + filenamelen + 1);
|
||||
path.alloc = baselen + filenamelen + 1;
|
||||
}
|
||||
memcpy(path.buf, base, baselen);
|
||||
memcpy(path.buf + baselen, filename, filenamelen);
|
||||
path.len = baselen + filenamelen;
|
||||
if (S_ISDIR(mode)) {
|
||||
path.buf[path.len] = '\0';
|
||||
if (S_ISDIR(mode) || S_ISDIRLNK(mode)) {
|
||||
strbuf_append_string(&path, "/");
|
||||
buffer = NULL;
|
||||
size = 0;
|
||||
} else {
|
||||
buffer = read_sha1_file(sha1, &type, &size);
|
||||
buffer = convert_sha1_file(path.buf, sha1, mode, &type, &size);
|
||||
if (!buffer)
|
||||
die("cannot read %s", sha1_to_hex(sha1));
|
||||
}
|
||||
|
||||
@@ -182,10 +182,10 @@ static int write_zip_entry(const unsigned char *sha1,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (S_ISDIR(mode)) {
|
||||
if (S_ISDIR(mode) || S_ISDIRLNK(mode)) {
|
||||
method = 0;
|
||||
attr2 = 16;
|
||||
result = READ_TREE_RECURSIVE;
|
||||
result = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
|
||||
out = NULL;
|
||||
uncompressed_size = 0;
|
||||
compressed_size = 0;
|
||||
@@ -195,7 +195,7 @@ static int write_zip_entry(const unsigned char *sha1,
|
||||
if (S_ISREG(mode) && zlib_compression_level != 0)
|
||||
method = 8;
|
||||
result = 0;
|
||||
buffer = read_sha1_file(sha1, &type, &size);
|
||||
buffer = convert_sha1_file(path, sha1, mode, &type, &size);
|
||||
if (!buffer)
|
||||
die("cannot read %s", sha1_to_hex(sha1));
|
||||
crc = crc32(crc, buffer, size);
|
||||
|
||||
@@ -23,7 +23,7 @@ sha_transform:
|
||||
stmfd sp!, {r4 - r8, lr}
|
||||
|
||||
@ for (i = 0; i < 16; i++)
|
||||
@ W[i] = ntohl(((uint32_t *)data)[i]); */
|
||||
@ W[i] = ntohl(((uint32_t *)data)[i]);
|
||||
|
||||
#ifdef __ARMEB__
|
||||
mov r4, r0
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
static const char builtin_add_usage[] =
|
||||
"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] <filepattern>...";
|
||||
|
||||
static int take_all_worktree_changes;
|
||||
static int take_worktree_changes;
|
||||
static const char *excludes_file;
|
||||
|
||||
static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
|
||||
@@ -122,11 +122,12 @@ static void update_callback(struct diff_queue_struct *q,
|
||||
}
|
||||
}
|
||||
|
||||
static void update_all(int verbose)
|
||||
static void update(int verbose, const char **files)
|
||||
{
|
||||
struct rev_info rev;
|
||||
init_revisions(&rev, "");
|
||||
setup_revisions(0, NULL, &rev, NULL);
|
||||
rev.prune_data = get_pathspec(rev.prefix, files);
|
||||
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
|
||||
rev.diffopt.format_callback = update_callback;
|
||||
rev.diffopt.format_callback_data = &verbose;
|
||||
@@ -200,16 +201,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "-u")) {
|
||||
take_all_worktree_changes = 1;
|
||||
take_worktree_changes = 1;
|
||||
continue;
|
||||
}
|
||||
usage(builtin_add_usage);
|
||||
}
|
||||
|
||||
if (take_all_worktree_changes) {
|
||||
if (i < argc)
|
||||
die("-u and explicit paths are incompatible");
|
||||
update_all(verbose);
|
||||
if (take_worktree_changes) {
|
||||
update(verbose, argv + i);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ static void *read_patch_file(int fd, unsigned long *sizep)
|
||||
void *buffer = xmalloc(alloc);
|
||||
|
||||
for (;;) {
|
||||
int nr = alloc - size;
|
||||
ssize_t nr = alloc - size;
|
||||
if (nr < 1024) {
|
||||
alloc += CHUNKSIZE;
|
||||
buffer = xrealloc(buffer, alloc);
|
||||
@@ -1468,7 +1468,7 @@ static int read_old_data(struct stat *st, const char *path, char **buf_p, unsign
|
||||
return error("unable to open %s", path);
|
||||
got = 0;
|
||||
for (;;) {
|
||||
int ret = xread(fd, buf + got, size - got);
|
||||
ssize_t ret = xread(fd, buf + got, size - got);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
got += ret;
|
||||
@@ -2009,6 +2009,29 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_to_create_blob(const char *new_name, int ok_if_exists)
|
||||
{
|
||||
struct stat nst;
|
||||
if (!lstat(new_name, &nst)) {
|
||||
if (S_ISDIR(nst.st_mode) || ok_if_exists)
|
||||
return 0;
|
||||
/*
|
||||
* A leading component of new_name might be a symlink
|
||||
* that is going to be removed with this patch, but
|
||||
* still pointing at somewhere that has the path.
|
||||
* In such a case, path "new_name" does not exist as
|
||||
* far as git is concerned.
|
||||
*/
|
||||
if (has_symlink_leading_path(new_name, NULL))
|
||||
return 0;
|
||||
|
||||
return error("%s: already exists in working directory", new_name);
|
||||
}
|
||||
else if ((errno != ENOENT) && (errno != ENOTDIR))
|
||||
return error("%s: %s", new_name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_patch(struct patch *patch, struct patch *prev_patch)
|
||||
{
|
||||
struct stat st;
|
||||
@@ -2095,15 +2118,9 @@ static int check_patch(struct patch *patch, struct patch *prev_patch)
|
||||
!ok_if_exists)
|
||||
return error("%s: already exists in index", new_name);
|
||||
if (!cached) {
|
||||
struct stat nst;
|
||||
if (!lstat(new_name, &nst)) {
|
||||
if (S_ISDIR(nst.st_mode) || ok_if_exists)
|
||||
; /* ok */
|
||||
else
|
||||
return error("%s: already exists in working directory", new_name);
|
||||
}
|
||||
else if ((errno != ENOENT) && (errno != ENOTDIR))
|
||||
return error("%s: %s", new_name, strerror(errno));
|
||||
int err = check_to_create_blob(new_name, ok_if_exists);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (!patch->new_mode) {
|
||||
if (0 < patch->is_new)
|
||||
|
||||
@@ -48,7 +48,7 @@ static int read_string(int fd, char *buffer, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size - 1; i++) {
|
||||
int count = xread(fd, buffer + i, 1);
|
||||
ssize_t count = xread(fd, buffer + i, 1);
|
||||
if (count < 0)
|
||||
return error("Read error: %s", strerror(errno));
|
||||
if (count == 0) {
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
static char *get_stdin(void)
|
||||
{
|
||||
int offset = 0;
|
||||
size_t offset = 0;
|
||||
char *data = xmalloc(CHUNK_SIZE);
|
||||
|
||||
while (1) {
|
||||
int cnt = xread(0, data + offset, CHUNK_SIZE);
|
||||
ssize_t cnt = xread(0, data + offset, CHUNK_SIZE);
|
||||
if (cnt < 0)
|
||||
die("error reading standard input: %s",
|
||||
strerror(errno));
|
||||
|
||||
@@ -454,7 +454,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
|
||||
/*
|
||||
* Parse the arguments before setup_revisions(), or something
|
||||
* like "git fmt-patch -o a123 HEAD^.." may fail; a123 is
|
||||
* like "git format-patch -o a123 HEAD^.." may fail; a123 is
|
||||
* possibly a valid SHA1.
|
||||
*/
|
||||
for (i = 1, j = 1; i < argc; i++) {
|
||||
|
||||
@@ -58,7 +58,10 @@ copy_data:
|
||||
parents = parents->next, parent_number++) {
|
||||
if (parent_number > 1) {
|
||||
int len = strlen(tip_name);
|
||||
char *new_name = xmalloc(len + 8);
|
||||
char *new_name = xmalloc(len +
|
||||
1 + decimal_length(generation) + /* ~<n> */
|
||||
1 + 2 + /* ^NN */
|
||||
1);
|
||||
|
||||
if (len > 2 && !strcmp(tip_name + len - 2, "^0"))
|
||||
len -= 2;
|
||||
|
||||
@@ -34,7 +34,7 @@ static void *fill(int min)
|
||||
offset = 0;
|
||||
}
|
||||
do {
|
||||
int ret = xread(0, buffer + len, sizeof(buffer) - len);
|
||||
ssize_t ret = xread(0, buffer + len, sizeof(buffer) - len);
|
||||
if (ret <= 0) {
|
||||
if (!ret)
|
||||
die("early EOF");
|
||||
|
||||
2
cache.h
2
cache.h
@@ -411,6 +411,7 @@ struct checkout {
|
||||
};
|
||||
|
||||
extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
|
||||
extern int has_symlink_leading_path(const char *name, char *last_symlink);
|
||||
|
||||
extern struct alternate_object_database {
|
||||
struct alternate_object_database *next;
|
||||
@@ -548,6 +549,7 @@ extern void trace_argv_printf(const char **argv, int count, const char *format,
|
||||
/* convert.c */
|
||||
extern char *convert_to_git(const char *path, const char *src, unsigned long *sizep);
|
||||
extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep);
|
||||
extern void *convert_sha1_file(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size);
|
||||
|
||||
/* match-trees.c */
|
||||
void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int);
|
||||
|
||||
@@ -714,7 +714,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
|
||||
result_size = len;
|
||||
result = xmalloc(len + 1);
|
||||
while (sz < len) {
|
||||
int done = xread(fd, result+sz, len-sz);
|
||||
ssize_t done = xread(fd, result+sz, len-sz);
|
||||
if (done == 0)
|
||||
break;
|
||||
if (done < 0)
|
||||
|
||||
1
commit.c
1
commit.c
@@ -1063,6 +1063,7 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
|
||||
int sz;
|
||||
char header[512];
|
||||
const char *header_fmt =
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=%s\n"
|
||||
"Content-Transfer-Encoding: 8bit\n";
|
||||
sz = snprintf(header, sizeof(header), header_fmt,
|
||||
|
||||
28
config.c
28
config.c
@@ -451,6 +451,9 @@ static int matches(const char* key, const char* value)
|
||||
|
||||
static int store_aux(const char* key, const char* value)
|
||||
{
|
||||
const char *ep;
|
||||
size_t section_len;
|
||||
|
||||
switch (store.state) {
|
||||
case KEY_SEEN:
|
||||
if (matches(key, value)) {
|
||||
@@ -468,12 +471,29 @@ static int store_aux(const char* key, const char* value)
|
||||
}
|
||||
break;
|
||||
case SECTION_SEEN:
|
||||
if (strncmp(key, store.key, store.baselen+1)) {
|
||||
/*
|
||||
* What we are looking for is in store.key (both
|
||||
* section and var), and its section part is baselen
|
||||
* long. We found key (again, both section and var).
|
||||
* We would want to know if this key is in the same
|
||||
* section as what we are looking for. We already
|
||||
* know we are in the same section as what should
|
||||
* hold store.key.
|
||||
*/
|
||||
ep = strrchr(key, '.');
|
||||
section_len = ep - key;
|
||||
|
||||
if ((section_len != store.baselen) ||
|
||||
memcmp(key, store.key, section_len+1)) {
|
||||
store.state = SECTION_END_SEEN;
|
||||
break;
|
||||
} else
|
||||
/* do not increment matches: this is no match */
|
||||
store.offset[store.seen] = ftell(config_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not increment matches: this is no match, but we
|
||||
* just made sure we are in the desired section.
|
||||
*/
|
||||
store.offset[store.seen] = ftell(config_file);
|
||||
/* fallthru */
|
||||
case SECTION_END_SEEN:
|
||||
case START:
|
||||
|
||||
@@ -75,7 +75,7 @@ foreach my $tar_file (@ARGV)
|
||||
$mode = oct $mode;
|
||||
$size = oct $size;
|
||||
$mtime = oct $mtime;
|
||||
next if $mode & 0040000;
|
||||
next if $typeflag == 5; # directory
|
||||
|
||||
print FI "blob\n", "mark :$next_mark\n", "data $size\n";
|
||||
while ($size > 0 && read(I, $_, 512) == 512) {
|
||||
|
||||
63
convert.c
63
convert.c
@@ -86,7 +86,7 @@ static char *crlf_to_git(const char *path, const char *src, unsigned long *sizep
|
||||
unsigned long size, nsize;
|
||||
struct text_stat stats;
|
||||
|
||||
if ((action == CRLF_BINARY) || (action == CRLF_GUESS && !auto_crlf))
|
||||
if ((action == CRLF_BINARY) || !auto_crlf)
|
||||
return NULL;
|
||||
|
||||
size = *sizep;
|
||||
@@ -154,7 +154,7 @@ static char *crlf_to_worktree(const char *path, const char *src, unsigned long *
|
||||
unsigned char last;
|
||||
|
||||
if ((action == CRLF_BINARY) || (action == CRLF_INPUT) ||
|
||||
(action == CRLF_GUESS && auto_crlf <= 0))
|
||||
auto_crlf <= 0)
|
||||
return NULL;
|
||||
|
||||
size = *sizep;
|
||||
@@ -412,7 +412,7 @@ static void setup_convert_check(struct git_attr_check *check)
|
||||
static int count_ident(const char *cp, unsigned long size)
|
||||
{
|
||||
/*
|
||||
* "$ident: 0000000000000000000000000000000000000000 $" <=> "$ident$"
|
||||
* "$Id: 0000000000000000000000000000000000000000 $" <=> "$Id$"
|
||||
*/
|
||||
int cnt = 0;
|
||||
char ch;
|
||||
@@ -422,20 +422,20 @@ static int count_ident(const char *cp, unsigned long size)
|
||||
size--;
|
||||
if (ch != '$')
|
||||
continue;
|
||||
if (size < 6)
|
||||
if (size < 3)
|
||||
break;
|
||||
if (memcmp("ident", cp, 5))
|
||||
if (memcmp("Id", cp, 2))
|
||||
continue;
|
||||
ch = cp[5];
|
||||
cp += 6;
|
||||
size -= 6;
|
||||
ch = cp[2];
|
||||
cp += 3;
|
||||
size -= 3;
|
||||
if (ch == '$')
|
||||
cnt++; /* $ident$ */
|
||||
cnt++; /* $Id$ */
|
||||
if (ch != ':')
|
||||
continue;
|
||||
|
||||
/*
|
||||
* "$ident: ... "; scan up to the closing dollar sign and discard.
|
||||
* "$Id: ... "; scan up to the closing dollar sign and discard.
|
||||
*/
|
||||
while (size) {
|
||||
ch = *cp++;
|
||||
@@ -466,10 +466,10 @@ static char *ident_to_git(const char *path, const char *src, unsigned long *size
|
||||
for (dst = buf; size; size--) {
|
||||
char ch = *src++;
|
||||
*dst++ = ch;
|
||||
if ((ch == '$') && (6 <= size) &&
|
||||
!memcmp("ident:", src, 6)) {
|
||||
unsigned long rem = size - 6;
|
||||
const char *cp = src + 6;
|
||||
if ((ch == '$') && (3 <= size) &&
|
||||
!memcmp("Id:", src, 3)) {
|
||||
unsigned long rem = size - 3;
|
||||
const char *cp = src + 3;
|
||||
do {
|
||||
ch = *cp++;
|
||||
if (ch == '$')
|
||||
@@ -478,8 +478,8 @@ static char *ident_to_git(const char *path, const char *src, unsigned long *size
|
||||
} while (rem);
|
||||
if (!rem)
|
||||
continue;
|
||||
memcpy(dst, "ident$", 6);
|
||||
dst += 6;
|
||||
memcpy(dst, "Id$", 3);
|
||||
dst += 3;
|
||||
size -= (cp - src);
|
||||
src = cp;
|
||||
}
|
||||
@@ -511,13 +511,13 @@ static char *ident_to_worktree(const char *path, const char *src, unsigned long
|
||||
const char *cp;
|
||||
char ch = *src++;
|
||||
*dst++ = ch;
|
||||
if ((ch != '$') || (size < 6) || memcmp("ident", src, 5))
|
||||
if ((ch != '$') || (size < 3) || memcmp("Id", src, 2))
|
||||
continue;
|
||||
|
||||
if (src[5] == ':') {
|
||||
if (src[2] == ':') {
|
||||
/* discard up to but not including the closing $ */
|
||||
unsigned long rem = size - 6;
|
||||
cp = src + 6;
|
||||
unsigned long rem = size - 3;
|
||||
cp = src + 3;
|
||||
do {
|
||||
ch = *cp++;
|
||||
if (ch == '$')
|
||||
@@ -527,13 +527,13 @@ static char *ident_to_worktree(const char *path, const char *src, unsigned long
|
||||
if (!rem)
|
||||
continue;
|
||||
size -= (cp - src);
|
||||
} else if (src[5] == '$')
|
||||
cp = src + 5;
|
||||
} else if (src[2] == '$')
|
||||
cp = src + 2;
|
||||
else
|
||||
continue;
|
||||
|
||||
memcpy(dst, "ident: ", 7);
|
||||
dst += 7;
|
||||
memcpy(dst, "Id: ", 4);
|
||||
dst += 4;
|
||||
memcpy(dst, sha1_to_hex(sha1), 40);
|
||||
dst += 40;
|
||||
*dst++ = ' ';
|
||||
@@ -652,3 +652,18 @@ char *convert_to_working_tree(const char *path, const char *src, unsigned long *
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void *convert_sha1_file(const char *path, const unsigned char *sha1,
|
||||
unsigned int mode, enum object_type *type,
|
||||
unsigned long *size)
|
||||
{
|
||||
void *buffer = read_sha1_file(sha1, type, size);
|
||||
if (S_ISREG(mode) && buffer) {
|
||||
void *converted = convert_to_working_tree(path, buffer, size);
|
||||
if (converted) {
|
||||
free(buffer);
|
||||
buffer = converted;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
3
copy.c
3
copy.c
@@ -3,10 +3,9 @@
|
||||
int copy_fd(int ifd, int ofd)
|
||||
{
|
||||
while (1) {
|
||||
int len;
|
||||
char buffer[8192];
|
||||
char *buf = buffer;
|
||||
len = xread(ifd, buffer, sizeof(buffer));
|
||||
ssize_t len = xread(ifd, buffer, sizeof(buffer));
|
||||
if (!len)
|
||||
break;
|
||||
if (len < 0) {
|
||||
|
||||
2
diff.c
2
diff.c
@@ -1412,7 +1412,7 @@ static int populate_from_stdin(struct diff_filespec *s)
|
||||
#define INCREMENT 1024
|
||||
char *buf;
|
||||
unsigned long size;
|
||||
int got;
|
||||
ssize_t got;
|
||||
|
||||
size = 0;
|
||||
buf = NULL;
|
||||
|
||||
@@ -22,10 +22,10 @@ get_repo_base() {
|
||||
cd "`/bin/pwd`" &&
|
||||
cd "$1" &&
|
||||
{
|
||||
cd .git 2>/dev/null
|
||||
cd .git
|
||||
pwd
|
||||
}
|
||||
)
|
||||
) 2>/dev/null
|
||||
}
|
||||
|
||||
if [ -n "$GIT_SSL_NO_VERIFY" ]; then
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
|
||||
#define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
|
||||
|
||||
/* Approximation of the length of the decimal representation of this type. */
|
||||
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__)
|
||||
#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
|
||||
#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
|
||||
|
||||
@@ -160,36 +160,51 @@ foreach my $p (@afiles) {
|
||||
}
|
||||
}
|
||||
|
||||
# ... check dirs,
|
||||
foreach my $d (@dirs) {
|
||||
if (-e $d) {
|
||||
$dirty = 1;
|
||||
warn "$d exists and is not a directory!\n";
|
||||
}
|
||||
}
|
||||
foreach my $f (@afiles) {
|
||||
# This should return only one value
|
||||
if ($f =~ m,(.*)/[^/]*$,) {
|
||||
my $p = $1;
|
||||
next if (grep { $_ eq $p } @dirs);
|
||||
}
|
||||
my @status = grep(m/^File/, safe_pipe_capture(@cvs, '-q', 'status' ,$f));
|
||||
if (@status > 1) { warn 'Strange! cvs status returned more than one line?'};
|
||||
if (-d dirname $f and $status[0] !~ m/Status: Unknown$/
|
||||
and $status[0] !~ m/^File: no file /) {
|
||||
$dirty = 1;
|
||||
warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n";
|
||||
warn "Status was: $status[0]\n";
|
||||
|
||||
# ... query status of all files that we have a directory for and parse output of 'cvs status' to %cvsstat.
|
||||
my @canstatusfiles;
|
||||
foreach my $f (@files) {
|
||||
my $path = dirname $f;
|
||||
next if (grep { $_ eq $path } @dirs);
|
||||
push @canstatusfiles, $f;
|
||||
}
|
||||
|
||||
my %cvsstat;
|
||||
if (@canstatusfiles) {
|
||||
my @cvsoutput;
|
||||
@cvsoutput= safe_pipe_capture(@cvs, 'status', @canstatusfiles);
|
||||
my $matchcount = 0;
|
||||
foreach my $l (@cvsoutput) {
|
||||
chomp $l;
|
||||
if ( $l =~ /^File:/ and $l =~ /Status: (.*)$/ ) {
|
||||
$cvsstat{$canstatusfiles[$matchcount]} = $1;
|
||||
$matchcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ... validate new files,
|
||||
foreach my $f (@afiles) {
|
||||
if (defined ($cvsstat{$f}) and $cvsstat{$f} ne "Unknown") {
|
||||
$dirty = 1;
|
||||
warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n";
|
||||
warn "Status was: $cvsstat{$f}\n";
|
||||
}
|
||||
}
|
||||
# ... validate known files.
|
||||
foreach my $f (@files) {
|
||||
next if grep { $_ eq $f } @afiles;
|
||||
# TODO:we need to handle removed in cvs
|
||||
my @status = grep(m/^File/, safe_pipe_capture(@cvs, '-q', 'status' ,$f));
|
||||
if (@status > 1) { warn 'Strange! cvs status returned more than one line?'};
|
||||
unless ($status[0] =~ m/Status: Up-to-date$/) {
|
||||
unless (defined ($cvsstat{$f}) and $cvsstat{$f} eq "Up-to-date") {
|
||||
$dirty = 1;
|
||||
warn "File $f not up to date in your CVS checkout!\n";
|
||||
warn "File $f not up to date but has status '$cvsstat{$f}' in your CVS checkout!\n";
|
||||
}
|
||||
}
|
||||
if ($dirty) {
|
||||
|
||||
@@ -105,6 +105,7 @@ if (@ARGV && $ARGV[0] eq 'pserver') {
|
||||
unless ($line eq 'anonymous') {
|
||||
print "E Only anonymous user allowed via pserver\n";
|
||||
print "I HATE YOU\n";
|
||||
exit 1;
|
||||
}
|
||||
$line = <STDIN>; chomp $line; # validate the password?
|
||||
$line = <STDIN>; chomp $line;
|
||||
@@ -183,9 +184,9 @@ sub req_Root
|
||||
}
|
||||
foreach my $line ( @gitvars )
|
||||
{
|
||||
next unless ( $line =~ /^(.*?)\.(.*?)(?:\.(.*?))?=(.*)$/ );
|
||||
unless ($3) {
|
||||
$cfg->{$1}{$2} = $4;
|
||||
next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
|
||||
unless ($2) {
|
||||
$cfg->{$1}{$3} = $4;
|
||||
} else {
|
||||
$cfg->{$1}{$2}{$3} = $4;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ SCRIPT_SH = git-gui.sh
|
||||
GITGUI_BUILT_INS = git-citool
|
||||
ALL_PROGRAMS = $(GITGUI_BUILT_INS) $(patsubst %.sh,%,$(SCRIPT_SH))
|
||||
ALL_LIBFILES = $(wildcard lib/*.tcl)
|
||||
PRELOAD_FILES = lib/class.tcl
|
||||
|
||||
ifndef SHELL_PATH
|
||||
SHELL_PATH = /bin/sh
|
||||
@@ -32,6 +33,7 @@ ifndef V
|
||||
QUIET_GEN = @echo ' ' GEN $@;
|
||||
QUIET_BUILT_IN = @echo ' ' BUILTIN $@;
|
||||
QUIET_INDEX = @echo ' ' INDEX $(dir $@);
|
||||
QUIET_2DEVNULL = 2>/dev/null
|
||||
endif
|
||||
|
||||
TCL_PATH ?= tclsh
|
||||
@@ -45,6 +47,7 @@ endif
|
||||
DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
|
||||
gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
|
||||
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
|
||||
TCL_PATH_SQ = $(subst ','\'',$(TCL_PATH))
|
||||
TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
|
||||
|
||||
libdir ?= $(sharedir)/git-gui/lib
|
||||
@@ -64,16 +67,26 @@ $(GITGUI_BUILT_INS): git-gui
|
||||
$(QUIET_BUILT_IN)rm -f $@ && ln git-gui $@
|
||||
|
||||
lib/tclIndex: $(ALL_LIBFILES)
|
||||
$(QUIET_INDEX)echo \
|
||||
source lib/class.tcl \; \
|
||||
$(QUIET_INDEX)if echo \
|
||||
$(foreach p,$(PRELOAD_FILES),source $p\;) \
|
||||
auto_mkindex lib '*.tcl' \
|
||||
| $(TCL_PATH)
|
||||
| $(TCL_PATH) $(QUIET_2DEVNULL); then : ok; \
|
||||
else \
|
||||
echo 1>&2 " * $(TCL_PATH) failed; using unoptimized loading"; \
|
||||
rm -f $@ ; \
|
||||
echo '# Autogenerated by git-gui Makefile' >$@ && \
|
||||
echo >>$@ && \
|
||||
$(foreach p,$(PRELOAD_FILES) $(ALL_LIBFILES),echo '$(subst lib/,,$p)' >>$@ &&) \
|
||||
echo >>$@ ; \
|
||||
fi
|
||||
|
||||
# These can record GITGUI_VERSION
|
||||
$(patsubst %.sh,%,$(SCRIPT_SH)): GIT-VERSION-FILE GIT-GUI-VARS
|
||||
lib/tclIndex: GIT-GUI-VARS
|
||||
|
||||
TRACK_VARS = \
|
||||
$(subst ','\'',SHELL_PATH='$(SHELL_PATH_SQ)') \
|
||||
$(subst ','\'',TCL_PATH='$(TCL_PATH_SQ)') \
|
||||
$(subst ','\'',TCLTK_PATH='$(TCLTK_PATH_SQ)') \
|
||||
$(subst ','\'',libdir='$(libdir_SQ)') \
|
||||
#end TRACK_VARS
|
||||
|
||||
@@ -28,7 +28,34 @@ set oguilib {@@GITGUI_LIBDIR@@}
|
||||
if {[string match @@* $oguilib]} {
|
||||
set oguilib [file join [file dirname [file normalize $argv0]] lib]
|
||||
}
|
||||
set auto_path [concat [list $oguilib] $auto_path]
|
||||
set idx [file join $oguilib tclIndex]
|
||||
catch {
|
||||
set fd [open $idx r]
|
||||
if {[gets $fd] eq {# Autogenerated by git-gui Makefile}} {
|
||||
set idx [list]
|
||||
while {[gets $fd n] >= 0} {
|
||||
if {$n ne {} && ![string match #* $n]} {
|
||||
lappend idx $n
|
||||
}
|
||||
}
|
||||
} else {
|
||||
set idx {}
|
||||
}
|
||||
close $fd
|
||||
}
|
||||
if {$idx ne {}} {
|
||||
set loaded [list]
|
||||
foreach p $idx {
|
||||
if {[lsearch -exact $loaded $p] >= 0} continue
|
||||
puts $p
|
||||
source [file join $oguilib $p]
|
||||
lappend loaded $p
|
||||
}
|
||||
unset loaded p
|
||||
} else {
|
||||
set auto_path [concat [list $oguilib] $auto_path]
|
||||
}
|
||||
unset -nocomplain fd idx
|
||||
|
||||
if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} {
|
||||
unset _verbose
|
||||
|
||||
@@ -143,13 +143,13 @@ canon_refs_list_for_fetch () {
|
||||
fi
|
||||
case "$remote" in
|
||||
'' | HEAD ) remote=HEAD ;;
|
||||
refs/heads/* | refs/tags/* | refs/remotes/*) ;;
|
||||
refs/*) ;;
|
||||
heads/* | tags/* | remotes/* ) remote="refs/$remote" ;;
|
||||
*) remote="refs/heads/$remote" ;;
|
||||
esac
|
||||
case "$local" in
|
||||
'') local= ;;
|
||||
refs/heads/* | refs/tags/* | refs/remotes/*) ;;
|
||||
refs/*) ;;
|
||||
heads/* | tags/* | remotes/* ) local="refs/$local" ;;
|
||||
*) local="refs/heads/$local" ;;
|
||||
esac
|
||||
|
||||
@@ -212,7 +212,7 @@ my $aliasfiletype = $repo->config('sendemail.aliasfiletype');
|
||||
my %parse_alias = (
|
||||
# multiline formats can be supported in the future
|
||||
mutt => sub { my $fh = shift; while (<$fh>) {
|
||||
if (/^alias\s+(\S+)\s+(.*)$/) {
|
||||
if (/^\s*alias\s+(\S+)\s+(.*)$/) {
|
||||
my ($alias, $addr) = ($1, $2);
|
||||
$addr =~ s/#.*$//; # mutt allows # comments
|
||||
# commas delimit multiple addresses
|
||||
|
||||
83
git-svn.perl
83
git-svn.perl
@@ -80,6 +80,7 @@ my %icv;
|
||||
my %init_opts = ( 'template=s' => \$_template, 'shared:s' => \$_shared,
|
||||
'trunk|T=s' => \$_trunk, 'tags|t=s' => \$_tags,
|
||||
'branches|b=s' => \$_branches, 'prefix=s' => \$_prefix,
|
||||
'minimize-url|m' => \$Git::SVN::_minimize_url,
|
||||
'no-metadata' => sub { $icv{noMetadata} = 1 },
|
||||
'use-svm-props' => sub { $icv{useSvmProps} = 1 },
|
||||
'use-svnsync-props' => sub { $icv{useSvnsyncProps} = 1 },
|
||||
@@ -393,7 +394,7 @@ sub cmd_dcommit {
|
||||
} else {
|
||||
my %ed_opts = ( r => $last_rev,
|
||||
log => get_commit_entry($d)->{log},
|
||||
ra => Git::SVN::Ra->new($url),
|
||||
ra => Git::SVN::Ra->new($gs->full_url),
|
||||
tree_a => "$d~1",
|
||||
tree_b => $d,
|
||||
editor_cb => sub {
|
||||
@@ -484,6 +485,11 @@ sub cmd_multi_init {
|
||||
unless (defined $_trunk || defined $_branches || defined $_tags) {
|
||||
usage(1);
|
||||
}
|
||||
|
||||
# there are currently some bugs that prevent multi-init/multi-fetch
|
||||
# setups from working well without this.
|
||||
$Git::SVN::_minimize_url = 1;
|
||||
|
||||
$_prefix = '' unless defined $_prefix;
|
||||
if (defined $url) {
|
||||
$url =~ s#/+$##;
|
||||
@@ -820,7 +826,7 @@ use strict;
|
||||
use warnings;
|
||||
use vars qw/$default_repo_id $default_ref_id $_no_metadata $_follow_parent
|
||||
$_repack $_repack_flags $_use_svm_props $_head
|
||||
$_use_svnsync_props $no_reuse_existing/;
|
||||
$_use_svnsync_props $no_reuse_existing $_minimize_url/;
|
||||
use Carp qw/croak/;
|
||||
use File::Path qw/mkpath/;
|
||||
use File::Copy qw/copy/;
|
||||
@@ -1037,7 +1043,7 @@ sub init_remote_config {
|
||||
"[svn-remote \"$existing\"]\n";
|
||||
}
|
||||
$self->{repo_id} = $existing;
|
||||
} else {
|
||||
} elsif ($_minimize_url) {
|
||||
my $min_url = Git::SVN::Ra->new($url)->minimize_url;
|
||||
$existing = find_existing_remote($min_url, $r);
|
||||
if ($existing) {
|
||||
@@ -1390,7 +1396,7 @@ sub traverse_ignore {
|
||||
}
|
||||
}
|
||||
foreach (sort keys %$dirent) {
|
||||
next if $dirent->{$_}->kind != $SVN::Node::dir;
|
||||
next if $dirent->{$_}->{kind} != $SVN::Node::dir;
|
||||
$self->traverse_ignore($fh, "$path/$_", $r);
|
||||
}
|
||||
}
|
||||
@@ -2840,8 +2846,10 @@ sub close_edit {
|
||||
my ($self) = @_;
|
||||
my ($p,$bat) = ($self->{pool}, $self->{bat});
|
||||
foreach (sort { $b =~ tr#/#/# <=> $a =~ tr#/#/# } keys %$bat) {
|
||||
next if $_ eq '';
|
||||
$self->close_directory($bat->{$_}, $p);
|
||||
}
|
||||
$self->close_directory($bat->{''}, $p);
|
||||
$self->SUPER::close_edit($p);
|
||||
$p->clear;
|
||||
}
|
||||
@@ -2888,7 +2896,7 @@ my ($can_do_switch, %ignored_err, $RA);
|
||||
BEGIN {
|
||||
# enforce temporary pool usage for some simple functions
|
||||
my $e;
|
||||
foreach (qw/get_latest_revnum get_uuid get_repos_root/) {
|
||||
foreach (qw/rev_proplist get_latest_revnum get_uuid get_repos_root/) {
|
||||
$e .= "sub $_ {
|
||||
my \$self = shift;
|
||||
my \$pool = SVN::Pool->new;
|
||||
@@ -2897,36 +2905,13 @@ BEGIN {
|
||||
wantarray ? \@ret : \$ret[0]; }\n";
|
||||
}
|
||||
|
||||
# get_dir needs $pool held in cache for dirents to work,
|
||||
# check_path is cacheable and rev_proplist is close enough
|
||||
# for our purposes.
|
||||
foreach (qw/check_path get_dir rev_proplist/) {
|
||||
$e .= "my \%${_}_cache; my \$${_}_rev = 0; sub $_ {
|
||||
my \$self = shift;
|
||||
my \$r = pop;
|
||||
my \$k = join(\"\\0\", \@_);
|
||||
if (my \$x = \$${_}_cache{\$r}->{\$k}) {
|
||||
return wantarray ? \@\$x : \$x->[0];
|
||||
}
|
||||
my \$pool = SVN::Pool->new;
|
||||
my \@ret = \$self->SUPER::$_(\@_, \$r, \$pool);
|
||||
if (\$r != \$${_}_rev) {
|
||||
\%${_}_cache = ( pool => [] );
|
||||
\$${_}_rev = \$r;
|
||||
}
|
||||
\$${_}_cache{\$r}->{\$k} = \\\@ret;
|
||||
push \@{\$${_}_cache{pool}}, \$pool;
|
||||
wantarray ? \@ret : \$ret[0]; }\n";
|
||||
}
|
||||
$e .= "\n1;";
|
||||
eval $e or die $@;
|
||||
eval "$e; 1;" or die $@;
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, $url) = @_;
|
||||
$url =~ s!/+$!!;
|
||||
return $RA if ($RA && $RA->{url} eq $url);
|
||||
$RA->{pool}->clear if $RA;
|
||||
|
||||
SVN::_Core::svn_config_ensure($config_dir, undef);
|
||||
my ($baton, $callbacks) = SVN::Core::auth_open_helper([
|
||||
@@ -2952,9 +2937,47 @@ sub new {
|
||||
$self->{svn_path} = $url;
|
||||
$self->{repos_root} = $self->get_repos_root;
|
||||
$self->{svn_path} =~ s#^\Q$self->{repos_root}\E(/|$)##;
|
||||
$self->{cache} = { check_path => { r => 0, data => {} },
|
||||
get_dir => { r => 0, data => {} } };
|
||||
$RA = bless $self, $class;
|
||||
}
|
||||
|
||||
sub check_path {
|
||||
my ($self, $path, $r) = @_;
|
||||
my $cache = $self->{cache}->{check_path};
|
||||
if ($r == $cache->{r} && exists $cache->{data}->{$path}) {
|
||||
return $cache->{data}->{$path};
|
||||
}
|
||||
my $pool = SVN::Pool->new;
|
||||
my $t = $self->SUPER::check_path($path, $r, $pool);
|
||||
$pool->clear;
|
||||
if ($r != $cache->{r}) {
|
||||
%{$cache->{data}} = ();
|
||||
$cache->{r} = $r;
|
||||
}
|
||||
$cache->{data}->{$path} = $t;
|
||||
}
|
||||
|
||||
sub get_dir {
|
||||
my ($self, $dir, $r) = @_;
|
||||
my $cache = $self->{cache}->{get_dir};
|
||||
if ($r == $cache->{r}) {
|
||||
if (my $x = $cache->{data}->{$dir}) {
|
||||
return wantarray ? @$x : $x->[0];
|
||||
}
|
||||
}
|
||||
my $pool = SVN::Pool->new;
|
||||
my ($d, undef, $props) = $self->SUPER::get_dir($dir, $r, $pool);
|
||||
my %dirents = map { $_ => { kind => $d->{$_}->kind } } keys %$d;
|
||||
$pool->clear;
|
||||
if ($r != $cache->{r}) {
|
||||
%{$cache->{data}} = ();
|
||||
$cache->{r} = $r;
|
||||
}
|
||||
$cache->{data}->{$dir} = [ \%dirents, $r, $props ];
|
||||
wantarray ? (\%dirents, $r, $props) : \%dirents;
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
# do not call the real DESTROY since we store ourselves in $RA
|
||||
}
|
||||
@@ -3169,7 +3192,7 @@ sub match_globs {
|
||||
return unless scalar @x == 3;
|
||||
my $dirents = $x[0];
|
||||
foreach my $de (keys %$dirents) {
|
||||
next if $dirents->{$de}->kind != $SVN::Node::dir;
|
||||
next if $dirents->{$de}->{kind} != $SVN::Node::dir;
|
||||
my $p = $g->{path}->full_path($de);
|
||||
next if $exists->{$p};
|
||||
next if (length $g->{path}->{right} &&
|
||||
|
||||
@@ -185,8 +185,13 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{_datadir}/git-core/
|
||||
%doc README COPYING Documentation/*.txt
|
||||
%{!?_without_docs: %doc Documentation/*.html Documentation/howto}
|
||||
%{!?_without_docs: %doc Documentation/technical}
|
||||
|
||||
%changelog
|
||||
* Tue May 13 2007 Quy Tonthat <qtonthat@gmail.com>
|
||||
- Added lib files for git-gui
|
||||
- Added Documentation/technical (As needed by Git Users Manual)
|
||||
|
||||
* Tue May 8 2007 Quy Tonthat <qtonthat@gmail.com>
|
||||
- Added howto files
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: small;
|
||||
border: solid #d9d8d1;
|
||||
border-width: 1px;
|
||||
margin: 10px;
|
||||
@@ -483,3 +484,7 @@ span.atnight {
|
||||
span.match {
|
||||
color: #e00000;
|
||||
}
|
||||
|
||||
div.binary {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@@ -102,10 +102,13 @@ our %feature = (
|
||||
# 'override' => allow-override (boolean),
|
||||
# 'default' => [ default options...] (array reference)}
|
||||
#
|
||||
# if feature is overridable (it means that allow-override has true value,
|
||||
# if feature is overridable (it means that allow-override has true value),
|
||||
# then feature-sub will be called with default options as parameters;
|
||||
# return value of feature-sub indicates if to enable specified feature
|
||||
#
|
||||
# if there is no 'sub' key (no feature-sub), then feature cannot be
|
||||
# overriden
|
||||
#
|
||||
# use gitweb_check_feature(<feature>) to check if <feature> is enabled
|
||||
|
||||
# Enable the 'blame' blob view, showing the last commit that modified
|
||||
@@ -138,10 +141,24 @@ our %feature = (
|
||||
|
||||
# Enable text search, which will list the commits which match author,
|
||||
# committer or commit text to a given string. Enabled by default.
|
||||
# Project specific override is not supported.
|
||||
'search' => {
|
||||
'override' => 0,
|
||||
'default' => [1]},
|
||||
|
||||
# Enable grep search, which will list the files in currently selected
|
||||
# tree containing the given string. Enabled by default. This can be
|
||||
# potentially CPU-intensive, of course.
|
||||
|
||||
# To enable system wide have in $GITWEB_CONFIG
|
||||
# $feature{'grep'}{'default'} = [1];
|
||||
# To have project specific config enable override in $GITWEB_CONFIG
|
||||
# $feature{'grep'}{'override'} = 1;
|
||||
# and in project config gitweb.grep = 0|1;
|
||||
'grep' => {
|
||||
'override' => 0,
|
||||
'default' => [1]},
|
||||
|
||||
# Enable the pickaxe search, which will list the commits that modified
|
||||
# a given string in a file. This can be practical and quite faster
|
||||
# alternative to 'blame', but still potentially CPU-intensive.
|
||||
@@ -241,6 +258,18 @@ sub gitweb_have_snapshot {
|
||||
return $have_snapshot;
|
||||
}
|
||||
|
||||
sub feature_grep {
|
||||
my ($val) = git_get_project_config('grep', '--bool');
|
||||
|
||||
if ($val eq 'true') {
|
||||
return (1);
|
||||
} elsif ($val eq 'false') {
|
||||
return (0);
|
||||
}
|
||||
|
||||
return ($_[0]);
|
||||
}
|
||||
|
||||
sub feature_pickaxe {
|
||||
my ($val) = git_get_project_config('pickaxe', '--bool');
|
||||
|
||||
@@ -360,17 +389,6 @@ if (defined $page) {
|
||||
}
|
||||
}
|
||||
|
||||
our $searchtext = $cgi->param('s');
|
||||
if (defined $searchtext) {
|
||||
if ($searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) {
|
||||
die_error(undef, "Invalid search parameter");
|
||||
}
|
||||
if (length($searchtext) < 2) {
|
||||
die_error(undef, "At least two characters are required for search parameter");
|
||||
}
|
||||
$searchtext = quotemeta $searchtext;
|
||||
}
|
||||
|
||||
our $searchtype = $cgi->param('st');
|
||||
if (defined $searchtype) {
|
||||
if ($searchtype =~ m/[^a-z]/) {
|
||||
@@ -378,6 +396,18 @@ if (defined $searchtype) {
|
||||
}
|
||||
}
|
||||
|
||||
our $searchtext = $cgi->param('s');
|
||||
our $search_regexp;
|
||||
if (defined $searchtext) {
|
||||
if ($searchtype ne 'grep' and $searchtype ne 'pickaxe' and $searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) {
|
||||
die_error(undef, "Invalid search parameter");
|
||||
}
|
||||
if (length($searchtext) < 2) {
|
||||
die_error(undef, "At least two characters are required for search parameter");
|
||||
}
|
||||
$search_regexp = quotemeta $searchtext;
|
||||
}
|
||||
|
||||
# now read PATH_INFO and use it as alternative to parameters
|
||||
sub evaluate_path_info {
|
||||
return if defined $project;
|
||||
@@ -728,7 +758,9 @@ sub chop_str {
|
||||
sub age_class {
|
||||
my $age = shift;
|
||||
|
||||
if ($age < 60*60*2) {
|
||||
if (!defined $age) {
|
||||
return "noage";
|
||||
} elsif ($age < 60*60*2) {
|
||||
return "age0";
|
||||
} elsif ($age < 60*60*24*2) {
|
||||
return "age1";
|
||||
@@ -1060,6 +1092,11 @@ sub git_get_hash_by_path {
|
||||
my $line = <$fd>;
|
||||
close $fd or return undef;
|
||||
|
||||
if (!defined $line) {
|
||||
# there is no tree or hash given by $path at $base
|
||||
return undef;
|
||||
}
|
||||
|
||||
#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
|
||||
$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/;
|
||||
if (defined $type && $type ne $2) {
|
||||
@@ -1102,7 +1139,9 @@ sub git_get_project_description {
|
||||
open my $fd, "$projectroot/$path/description" or return undef;
|
||||
my $descr = <$fd>;
|
||||
close $fd;
|
||||
chomp $descr;
|
||||
if (defined $descr) {
|
||||
chomp $descr;
|
||||
}
|
||||
return $descr;
|
||||
}
|
||||
|
||||
@@ -1253,7 +1292,8 @@ sub git_get_last_activity {
|
||||
'refs/heads') or return;
|
||||
my $most_recent = <$fd>;
|
||||
close $fd or return;
|
||||
if ($most_recent =~ / (\d+) [-+][01]\d\d\d$/) {
|
||||
if (defined $most_recent &&
|
||||
$most_recent =~ / (\d+) [-+][01]\d\d\d$/) {
|
||||
my $timestamp = $1;
|
||||
my $age = time - $timestamp;
|
||||
return ($age, age_string($age));
|
||||
@@ -1376,8 +1416,12 @@ sub parse_commit_text {
|
||||
|
||||
pop @commit_lines; # Remove '\0'
|
||||
|
||||
if (! @commit_lines) {
|
||||
return;
|
||||
}
|
||||
|
||||
my $header = shift @commit_lines;
|
||||
if (!($header =~ m/^[0-9a-fA-F]{40}/)) {
|
||||
if ($header !~ m/^[0-9a-fA-F]{40}/) {
|
||||
return;
|
||||
}
|
||||
($co{'id'}, my @parents) = split ' ', $header;
|
||||
@@ -1884,6 +1928,8 @@ EOF
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "</div>\n";
|
||||
|
||||
my ($have_search) = gitweb_check_feature('search');
|
||||
if ((defined $project) && ($have_search)) {
|
||||
if (!defined $searchtext) {
|
||||
@@ -1906,14 +1952,13 @@ EOF
|
||||
$cgi->hidden(-name => "a") . "\n" .
|
||||
$cgi->hidden(-name => "h") . "\n" .
|
||||
$cgi->popup_menu(-name => 'st', -default => 'commit',
|
||||
-values => ['commit', 'author', 'committer', 'pickaxe']) .
|
||||
-values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) .
|
||||
$cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) .
|
||||
" search:\n",
|
||||
$cgi->textfield(-name => "s", -value => $searchtext) . "\n" .
|
||||
"</div>" .
|
||||
$cgi->end_form() . "\n";
|
||||
}
|
||||
print "</div>\n";
|
||||
}
|
||||
|
||||
sub git_footer_html {
|
||||
@@ -2660,9 +2705,10 @@ sub git_patchset_body {
|
||||
# check if current patch belong to current raw line
|
||||
# and parse raw git-diff line if needed
|
||||
if (defined $diffinfo &&
|
||||
defined $from_id && defined $to_id &&
|
||||
from_ids_eq($diffinfo->{'from_id'}, $from_id) &&
|
||||
$diffinfo->{'to_id'} eq $to_id) {
|
||||
# this is split patch
|
||||
# this is continuation of a split patch
|
||||
print "<div class=\"patch cont\">\n";
|
||||
} else {
|
||||
# advance raw git-diff output if needed
|
||||
@@ -2702,8 +2748,9 @@ sub git_patchset_body {
|
||||
delete $from{'href'};
|
||||
}
|
||||
}
|
||||
|
||||
$to{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'};
|
||||
if ($diffinfo->{'status'} ne "D") { # not deleted file
|
||||
if ($diffinfo->{'to_id'} ne ('0' x 40)) { # file exists in result
|
||||
$to{'href'} = href(action=>"blob", hash_base=>$hash,
|
||||
hash=>$diffinfo->{'to_id'},
|
||||
file_name=>$to{'file'});
|
||||
@@ -2859,7 +2906,14 @@ sub git_patchset_body {
|
||||
} continue {
|
||||
print "</div>\n"; # class="patch"
|
||||
}
|
||||
print "<div class=\"diff nodifferences\">No differences found</div>\n" if (!$patch_number);
|
||||
|
||||
if ($patch_number == 0) {
|
||||
if (@hash_parents > 1) {
|
||||
print "<div class=\"diff nodifferences\">Trivial merge</div>\n";
|
||||
} else {
|
||||
print "<div class=\"diff nodifferences\">No differences found</div>\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "</div>\n"; # class="patchset"
|
||||
}
|
||||
@@ -2973,7 +3027,7 @@ sub git_project_list_body {
|
||||
esc_html($pr->{'descr'})) . "</td>\n" .
|
||||
"<td><i>" . chop_str($pr->{'owner'}, 15) . "</i></td>\n";
|
||||
print "<td class=\"". age_class($pr->{'age'}) . "\">" .
|
||||
$pr->{'age_string'} . "</td>\n" .
|
||||
(defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
|
||||
"<td class=\"link\">" .
|
||||
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " .
|
||||
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " .
|
||||
@@ -3227,7 +3281,7 @@ sub git_search_grep_body {
|
||||
esc_html(chop_str($co{'title'}, 50)) . "<br/>");
|
||||
my $comment = $co{'comment'};
|
||||
foreach my $line (@$comment) {
|
||||
if ($line =~ m/^(.*)($searchtext)(.*)$/i) {
|
||||
if ($line =~ m/^(.*)($search_regexp)(.*)$/i) {
|
||||
my $lead = esc_html($1) || "";
|
||||
$lead = chop_str($lead, 30, 10);
|
||||
my $match = esc_html($2) || "";
|
||||
@@ -3325,7 +3379,7 @@ sub git_project_index {
|
||||
sub git_summary {
|
||||
my $descr = git_get_project_description($project) || "none";
|
||||
my %co = parse_commit("HEAD");
|
||||
my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'});
|
||||
my %cd = %co ? parse_date($co{'committer_epoch'}, $co{'committer_tz'}) : ();
|
||||
my $head = $co{'id'};
|
||||
|
||||
my $owner = git_get_project_owner($project);
|
||||
@@ -3348,8 +3402,11 @@ sub git_summary {
|
||||
print "<div class=\"title\"> </div>\n";
|
||||
print "<table cellspacing=\"0\">\n" .
|
||||
"<tr><td>description</td><td>" . esc_html($descr) . "</td></tr>\n" .
|
||||
"<tr><td>owner</td><td>$owner</td></tr>\n" .
|
||||
"<tr><td>last change</td><td>$cd{'rfc2822'}</td></tr>\n";
|
||||
"<tr><td>owner</td><td>$owner</td></tr>\n";
|
||||
if (defined $cd{'rfc2822'}) {
|
||||
print "<tr><td>last change</td><td>$cd{'rfc2822'}</td></tr>\n";
|
||||
}
|
||||
|
||||
# use per project git URL list in $projectroot/$project/cloneurl
|
||||
# or make project git URL from git base URL and project name
|
||||
my $url_tag = "URL";
|
||||
@@ -3372,11 +3429,13 @@ sub git_summary {
|
||||
|
||||
# we need to request one more than 16 (0..15) to check if
|
||||
# those 16 are all
|
||||
my @commitlist = parse_commits($head, 17);
|
||||
git_print_header_div('shortlog');
|
||||
git_shortlog_body(\@commitlist, 0, 15, $refs,
|
||||
$#commitlist <= 15 ? undef :
|
||||
$cgi->a({-href => href(action=>"shortlog")}, "..."));
|
||||
my @commitlist = $head ? parse_commits($head, 17) : ();
|
||||
if (@commitlist) {
|
||||
git_print_header_div('shortlog');
|
||||
git_shortlog_body(\@commitlist, 0, 15, $refs,
|
||||
$#commitlist <= 15 ? undef :
|
||||
$cgi->a({-href => href(action=>"shortlog")}, "..."));
|
||||
}
|
||||
|
||||
if (@taglist) {
|
||||
git_print_header_div('tags');
|
||||
@@ -3408,6 +3467,11 @@ sub git_tag {
|
||||
git_header_html();
|
||||
git_print_page_nav('','', $head,undef,$head);
|
||||
my %tag = parse_tag($hash);
|
||||
|
||||
if (! %tag) {
|
||||
die_error(undef, "Unknown tag object");
|
||||
}
|
||||
|
||||
git_print_header_div('commit', esc_html($tag{'name'}), $hash);
|
||||
print "<div class=\"title_text\">\n" .
|
||||
"<table cellspacing=\"0\">\n" .
|
||||
@@ -4587,6 +4651,12 @@ sub git_search {
|
||||
die_error('403 Permission denied', "Permission denied");
|
||||
}
|
||||
}
|
||||
if ($searchtype eq 'grep') {
|
||||
my ($have_grep) = gitweb_check_feature('grep');
|
||||
if (!$have_grep) {
|
||||
die_error('403 Permission denied', "Permission denied");
|
||||
}
|
||||
}
|
||||
|
||||
git_header_html();
|
||||
|
||||
@@ -4599,7 +4669,7 @@ sub git_search {
|
||||
} elsif ($searchtype eq 'committer') {
|
||||
$greptype = "--committer=";
|
||||
}
|
||||
$greptype .= $searchtext;
|
||||
$greptype .= $search_regexp;
|
||||
my @commitlist = parse_commits($hash, 101, (100 * $page), $greptype);
|
||||
|
||||
my $paging_nav = '';
|
||||
@@ -4648,8 +4718,10 @@ sub git_search {
|
||||
my $alternate = 1;
|
||||
$/ = "\n";
|
||||
my $git_command = git_cmd_str();
|
||||
my $searchqtext = $searchtext;
|
||||
$searchqtext =~ s/'/'\\''/;
|
||||
open my $fd, "-|", "$git_command rev-list $hash | " .
|
||||
"$git_command diff-tree -r --stdin -S\'$searchtext\'";
|
||||
"$git_command diff-tree -r --stdin -S\'$searchqtext\'";
|
||||
undef %co;
|
||||
my @files;
|
||||
while (my $line = <$fd>) {
|
||||
@@ -4703,6 +4775,73 @@ sub git_search {
|
||||
|
||||
print "</table>\n";
|
||||
}
|
||||
|
||||
if ($searchtype eq 'grep') {
|
||||
git_print_page_nav('','', $hash,$co{'tree'},$hash);
|
||||
git_print_header_div('commit', esc_html($co{'title'}), $hash);
|
||||
|
||||
print "<table cellspacing=\"0\">\n";
|
||||
my $alternate = 1;
|
||||
my $matches = 0;
|
||||
$/ = "\n";
|
||||
open my $fd, "-|", git_cmd(), 'grep', '-n', '-i', '-E', $searchtext, $co{'tree'};
|
||||
my $lastfile = '';
|
||||
while (my $line = <$fd>) {
|
||||
chomp $line;
|
||||
my ($file, $lno, $ltext, $binary);
|
||||
last if ($matches++ > 1000);
|
||||
if ($line =~ /^Binary file (.+) matches$/) {
|
||||
$file = $1;
|
||||
$binary = 1;
|
||||
} else {
|
||||
(undef, $file, $lno, $ltext) = split(/:/, $line, 4);
|
||||
}
|
||||
if ($file ne $lastfile) {
|
||||
$lastfile and print "</td></tr>\n";
|
||||
if ($alternate++) {
|
||||
print "<tr class=\"dark\">\n";
|
||||
} else {
|
||||
print "<tr class=\"light\">\n";
|
||||
}
|
||||
print "<td class=\"list\">".
|
||||
$cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
|
||||
file_name=>"$file"),
|
||||
-class => "list"}, esc_path($file));
|
||||
print "</td><td>\n";
|
||||
$lastfile = $file;
|
||||
}
|
||||
if ($binary) {
|
||||
print "<div class=\"binary\">Binary file</div>\n";
|
||||
} else {
|
||||
$ltext = untabify($ltext);
|
||||
if ($ltext =~ m/^(.*)($searchtext)(.*)$/i) {
|
||||
$ltext = esc_html($1, -nbsp=>1);
|
||||
$ltext .= '<span class="match">';
|
||||
$ltext .= esc_html($2, -nbsp=>1);
|
||||
$ltext .= '</span>';
|
||||
$ltext .= esc_html($3, -nbsp=>1);
|
||||
} else {
|
||||
$ltext = esc_html($ltext, -nbsp=>1);
|
||||
}
|
||||
print "<div class=\"pre\">" .
|
||||
$cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
|
||||
file_name=>"$file").'#l'.$lno,
|
||||
-class => "linenr"}, sprintf('%4i', $lno))
|
||||
. ' ' . $ltext . "</div>\n";
|
||||
}
|
||||
}
|
||||
if ($lastfile) {
|
||||
print "</td></tr>\n";
|
||||
if ($matches > 1000) {
|
||||
print "<div class=\"diff nodifferences\">Too many matches, listing trimmed</div>\n";
|
||||
}
|
||||
} else {
|
||||
print "<div class=\"diff nodifferences\">No matches found</div>\n";
|
||||
}
|
||||
close $fd;
|
||||
|
||||
print "</table>\n";
|
||||
}
|
||||
git_footer_html();
|
||||
}
|
||||
|
||||
@@ -4713,6 +4852,20 @@ sub git_search_help {
|
||||
<dl>
|
||||
<dt><b>commit</b></dt>
|
||||
<dd>The commit messages and authorship information will be scanned for the given string.</dd>
|
||||
EOT
|
||||
my ($have_grep) = gitweb_check_feature('grep');
|
||||
if ($have_grep) {
|
||||
print <<EOT;
|
||||
<dt><b>grep</b></dt>
|
||||
<dd>All files in the currently selected tree (HEAD unless you are explicitly browsing
|
||||
a different one) are searched for the given
|
||||
<a href="http://en.wikipedia.org/wiki/Regular_expression">regular expression</a>
|
||||
(POSIX extended) and the matches are listed. On large
|
||||
trees, this search can take a while and put some strain on the server, so please use it with
|
||||
some consideration.</dd>
|
||||
EOT
|
||||
}
|
||||
print <<EOT;
|
||||
<dt><b>author</b></dt>
|
||||
<dd>Name and e-mail of the change author and date of birth of the patch will be scanned for the given string.</dd>
|
||||
<dt><b>committer</b></dt>
|
||||
@@ -4887,7 +5040,8 @@ XML
|
||||
|
||||
# get list of changed files
|
||||
open my $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
|
||||
$co{'parent'}, $co{'id'}, "--", (defined $file_name ? $file_name : ())
|
||||
$co{'parent'} || "--root",
|
||||
$co{'id'}, "--", (defined $file_name ? $file_name : ())
|
||||
or next;
|
||||
my @difftree = map { chomp; $_ } <$fd>;
|
||||
close $fd
|
||||
|
||||
@@ -224,7 +224,7 @@ socket_perror( const char *func, Socket_t *sock, int ret )
|
||||
static int
|
||||
socket_read( Socket_t *sock, char *buf, int len )
|
||||
{
|
||||
int n = xread( sock->fd, buf, len );
|
||||
ssize_t n = xread( sock->fd, buf, len );
|
||||
if (n <= 0) {
|
||||
socket_perror( "read", sock, n );
|
||||
close( sock->fd );
|
||||
|
||||
@@ -82,7 +82,7 @@ static void *fill(int min)
|
||||
die("cannot fill %d bytes", min);
|
||||
flush();
|
||||
do {
|
||||
int ret = xread(input_fd, input_buffer + input_len,
|
||||
ssize_t ret = xread(input_fd, input_buffer + input_len,
|
||||
sizeof(input_buffer) - input_len);
|
||||
if (ret <= 0) {
|
||||
if (!ret)
|
||||
|
||||
@@ -25,7 +25,7 @@ void fixup_pack_header_footer(int pack_fd,
|
||||
|
||||
buf = xmalloc(buf_sz);
|
||||
for (;;) {
|
||||
size_t n = xread(pack_fd, buf, buf_sz);
|
||||
ssize_t n = xread(pack_fd, buf, buf_sz);
|
||||
if (!n)
|
||||
break;
|
||||
if (n < 0)
|
||||
|
||||
@@ -65,10 +65,10 @@ void packet_write(int fd, const char *fmt, ...)
|
||||
|
||||
static void safe_read(int fd, void *buffer, unsigned size)
|
||||
{
|
||||
int n = 0;
|
||||
size_t n = 0;
|
||||
|
||||
while (n < size) {
|
||||
int ret = xread(fd, (char *) buffer + n, size - n);
|
||||
ssize_t ret = xread(fd, (char *) buffer + n, size - n);
|
||||
if (ret < 0)
|
||||
die("read error (%s)", strerror(errno));
|
||||
if (!ret)
|
||||
|
||||
@@ -2286,7 +2286,7 @@ int read_pipe(int fd, char** return_buf, unsigned long* return_size)
|
||||
{
|
||||
char* buf = *return_buf;
|
||||
unsigned long size = *return_size;
|
||||
int iret;
|
||||
ssize_t iret;
|
||||
unsigned long off = 0;
|
||||
|
||||
do {
|
||||
|
||||
@@ -86,7 +86,7 @@ static int serve_ref(int fd_in, int fd_out)
|
||||
|
||||
static void service(int fd_in, int fd_out) {
|
||||
char type;
|
||||
int retval;
|
||||
ssize_t retval;
|
||||
do {
|
||||
retval = xread(fd_in, &type, 1);
|
||||
if (retval < 1) {
|
||||
|
||||
48
symlinks.c
Normal file
48
symlinks.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "cache.h"
|
||||
|
||||
int has_symlink_leading_path(const char *name, char *last_symlink)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
const char *sp, *ep;
|
||||
char *dp;
|
||||
|
||||
sp = name;
|
||||
dp = path;
|
||||
|
||||
if (last_symlink && *last_symlink) {
|
||||
size_t last_len = strlen(last_symlink);
|
||||
size_t len = strlen(name);
|
||||
if (last_len < len &&
|
||||
!strncmp(name, last_symlink, last_len) &&
|
||||
name[last_len] == '/')
|
||||
return 1;
|
||||
*last_symlink = '\0';
|
||||
}
|
||||
|
||||
while (1) {
|
||||
size_t len;
|
||||
struct stat st;
|
||||
|
||||
ep = strchr(sp, '/');
|
||||
if (!ep)
|
||||
break;
|
||||
len = ep - sp;
|
||||
if (PATH_MAX <= dp + len - path + 2)
|
||||
return 0; /* new name is longer than that??? */
|
||||
memcpy(dp, sp, len);
|
||||
dp[len] = 0;
|
||||
|
||||
if (lstat(path, &st))
|
||||
return 0;
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
if (last_symlink)
|
||||
strcpy(last_symlink, path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dp[len++] = '/';
|
||||
dp = dp + len;
|
||||
sp = ep + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -21,7 +21,7 @@ test_expect_success setup '
|
||||
{
|
||||
echo a b c d e f g h i j k l m
|
||||
echo n o p q r s t u v w x y z
|
||||
echo '\''$ident$'\''
|
||||
echo '\''$Id$'\''
|
||||
} >test &&
|
||||
cat test >test.t &&
|
||||
cat test >test.o &&
|
||||
@@ -31,7 +31,7 @@ test_expect_success setup '
|
||||
git checkout -- test test.t test.i
|
||||
'
|
||||
|
||||
script='s/^\$ident: \([0-9a-f]*\) \$/\1/p'
|
||||
script='s/^\$Id: \([0-9a-f]*\) \$/\1/p'
|
||||
|
||||
test_expect_success check '
|
||||
|
||||
|
||||
@@ -407,6 +407,25 @@ EOF
|
||||
test_expect_success "section was removed properly" \
|
||||
"git diff -u expect .git/config"
|
||||
|
||||
rm .git/config
|
||||
|
||||
cat > expect << EOF
|
||||
[gitcvs]
|
||||
enabled = true
|
||||
dbname = %Ggitcvs2.%a.%m.sqlite
|
||||
[gitcvs "ext"]
|
||||
dbname = %Ggitcvs1.%a.%m.sqlite
|
||||
EOF
|
||||
|
||||
test_expect_success 'section ending' '
|
||||
|
||||
git-config gitcvs.enabled true &&
|
||||
git-config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite &&
|
||||
git-config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite &&
|
||||
cmp .git/config expect
|
||||
|
||||
'
|
||||
|
||||
test_expect_success numbers '
|
||||
|
||||
git-config kilo.gram 1k &&
|
||||
|
||||
38
t/t2200-add-update.sh
Executable file
38
t/t2200-add-update.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='git-add -u with path limiting
|
||||
|
||||
This test creates a working tree state with three files:
|
||||
|
||||
top (previously committed, modified)
|
||||
dir/sub (previously committed, modified)
|
||||
dir/other (untracked)
|
||||
|
||||
and issues a git-add -u with path limiting on "dir" to add
|
||||
only the updates to dir/sub.'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup' '
|
||||
echo initial >top &&
|
||||
mkdir dir &&
|
||||
echo initial >dir/sub &&
|
||||
git-add dir/sub top &&
|
||||
git-commit -m initial &&
|
||||
echo changed >top &&
|
||||
echo changed >dir/sub &&
|
||||
echo other >dir/other
|
||||
'
|
||||
|
||||
test_expect_success 'update' 'git-add -u dir'
|
||||
|
||||
test_expect_success 'update touched correct path' \
|
||||
'test "`git-diff-files --name-status dir/sub`" = ""'
|
||||
|
||||
test_expect_success 'update did not touch other tracked files' \
|
||||
'test "`git-diff-files --name-status top`" = "M top"'
|
||||
|
||||
test_expect_success 'update did not touch untracked files' \
|
||||
'test "`git-diff-files --name-status dir/other`" = ""'
|
||||
|
||||
test_done
|
||||
56
t/t4122-apply-symlink-inside.sh
Executable file
56
t/t4122-apply-symlink-inside.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='apply to deeper directory without getting fooled with symlink'
|
||||
. ./test-lib.sh
|
||||
|
||||
lecho () {
|
||||
for l_
|
||||
do
|
||||
echo "$l_"
|
||||
done
|
||||
}
|
||||
|
||||
test_expect_success setup '
|
||||
|
||||
mkdir -p arch/i386/boot arch/x86_64 &&
|
||||
lecho 1 2 3 4 5 >arch/i386/boot/Makefile &&
|
||||
ln -s ../i386/boot arch/x86_64/boot &&
|
||||
git add . &&
|
||||
test_tick &&
|
||||
git commit -m initial &&
|
||||
git branch test &&
|
||||
|
||||
rm arch/x86_64/boot &&
|
||||
mkdir arch/x86_64/boot &&
|
||||
lecho 2 3 4 5 6 >arch/x86_64/boot/Makefile &&
|
||||
git add . &&
|
||||
test_tick &&
|
||||
git commit -a -m second &&
|
||||
|
||||
git format-patch --binary -1 --stdout >test.patch
|
||||
|
||||
'
|
||||
|
||||
test_expect_success apply '
|
||||
|
||||
git checkout test &&
|
||||
git diff --exit-code test &&
|
||||
git diff --exit-code --cached test &&
|
||||
git apply --index test.patch
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check result' '
|
||||
|
||||
git diff --exit-code master &&
|
||||
git diff --exit-code --cached master &&
|
||||
test_tick &&
|
||||
git commit -m replay &&
|
||||
T1=$(git rev-parse "master^{tree}") &&
|
||||
T2=$(git rev-parse "HEAD^{tree}") &&
|
||||
test "z$T1" = "z$T2"
|
||||
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -229,7 +229,7 @@ test_expect_failure 'exit if init-ing a would clobber a URL' "
|
||||
|
||||
test_expect_success \
|
||||
'init allows us to connect to another directory in the same repo' "
|
||||
git-svn init -i bar $svnrepo/bar &&
|
||||
git-svn init --minimize-url -i bar $svnrepo/bar &&
|
||||
git config --get svn-remote.svn.fetch \
|
||||
'^bar:refs/remotes/bar$' &&
|
||||
git config --get svn-remote.svn.fetch \
|
||||
|
||||
@@ -28,7 +28,7 @@ test_expect_success 'initialize repo' "
|
||||
"
|
||||
|
||||
test_expect_success 'init and fetch a moved directory' "
|
||||
git-svn init -i thunk $svnrepo/thunk &&
|
||||
git-svn init --minimize-url -i thunk $svnrepo/thunk &&
|
||||
git-svn fetch -i thunk &&
|
||||
test \"\`git-rev-parse --verify refs/remotes/thunk@2\`\" \
|
||||
= \"\`git-rev-parse --verify refs/remotes/thunk~1\`\" &&
|
||||
@@ -68,7 +68,8 @@ test_expect_success 'follow larger parent' "
|
||||
echo hi > import/trunk/thunk/bump/thud/file &&
|
||||
svn import -m 'import a larger parent' import $svnrepo/larger-parent &&
|
||||
svn cp -m 'hi' $svnrepo/larger-parent $svnrepo/another-larger &&
|
||||
git-svn init -i larger $svnrepo/another-larger/trunk/thunk/bump/thud &&
|
||||
git-svn init --minimize-url -i larger \
|
||||
$svnrepo/another-larger/trunk/thunk/bump/thud &&
|
||||
git-svn fetch -i larger &&
|
||||
git-rev-parse --verify refs/remotes/larger &&
|
||||
git-rev-parse --verify \
|
||||
@@ -90,14 +91,14 @@ test_expect_success 'follow higher-level parent' "
|
||||
cd ..
|
||||
svn mkdir -m 'new glob at top level' $svnrepo/glob &&
|
||||
svn mv -m 'move blob down a level' $svnrepo/blob $svnrepo/glob/blob &&
|
||||
git-svn init -i blob $svnrepo/glob/blob &&
|
||||
git-svn init --minimize-url -i blob $svnrepo/glob/blob &&
|
||||
git-svn fetch -i blob
|
||||
"
|
||||
|
||||
test_expect_success 'follow deleted directory' "
|
||||
svn mv -m 'bye!' $svnrepo/glob/blob/hi $svnrepo/glob/blob/bye &&
|
||||
svn rm -m 'remove glob' $svnrepo/glob &&
|
||||
git-svn init -i glob $svnrepo/glob &&
|
||||
git-svn init --minimize-url -i glob $svnrepo/glob &&
|
||||
git-svn fetch -i glob &&
|
||||
test \"\`git cat-file blob refs/remotes/glob:blob/bye\`\" = hi &&
|
||||
test \"\`git ls-tree refs/remotes/glob | wc -l \`\" -eq 1
|
||||
@@ -127,7 +128,7 @@ test_expect_success 'follow-parent avoids deleting relevant info' "
|
||||
poke native/t/c.t &&
|
||||
svn commit -m 'reorg test' &&
|
||||
cd .. &&
|
||||
git-svn init -i r9270-t \
|
||||
git-svn init --minimize-url -i r9270-t \
|
||||
$svnrepo/r9270/trunk/subversion/bindings/swig/perl/native/t &&
|
||||
git-svn fetch -i r9270-t &&
|
||||
test \`git rev-list r9270-t | wc -l\` -eq 2 &&
|
||||
@@ -137,7 +138,7 @@ test_expect_success 'follow-parent avoids deleting relevant info' "
|
||||
|
||||
test_expect_success "track initial change if it was only made to parent" "
|
||||
svn cp -m 'wheee!' $svnrepo/r9270/trunk $svnrepo/r9270/drunk &&
|
||||
git-svn init -i r9270-d \
|
||||
git-svn init --minimize-url -i r9270-d \
|
||||
$svnrepo/r9270/drunk/subversion/bindings/swig/perl/native/t &&
|
||||
git-svn fetch -i r9270-d &&
|
||||
test \`git rev-list r9270-d | wc -l\` -eq 3 &&
|
||||
|
||||
@@ -33,7 +33,7 @@ test_expect_success 'test the commit-diff command' "
|
||||
|
||||
test_expect_success 'commit-diff to a sub-directory (with git-svn config)' "
|
||||
svn import -m 'sub-directory' import $svnrepo/subdir &&
|
||||
git-svn init $svnrepo/subdir &&
|
||||
git-svn init --minimize-url $svnrepo/subdir &&
|
||||
git-svn fetch &&
|
||||
git-svn commit-diff -r3 '$prev' '$head' &&
|
||||
svn cat $svnrepo/subdir/readme > readme.2 &&
|
||||
|
||||
@@ -9,9 +9,10 @@ test_description='git-svn useSvmProps test'
|
||||
|
||||
test_expect_success 'load svm repo' "
|
||||
svnadmin load -q $rawsvnrepo < ../t9110/svm.dump &&
|
||||
git-svn init -R arr -i bar $svnrepo/mirror/arr &&
|
||||
git-svn init -R argh -i dir $svnrepo/mirror/argh &&
|
||||
git-svn init -R argh -i e $svnrepo/mirror/argh/a/b/c/d/e &&
|
||||
git-svn init --minimize-url -R arr -i bar $svnrepo/mirror/arr &&
|
||||
git-svn init --minimize-url -R argh -i dir $svnrepo/mirror/argh &&
|
||||
git-svn init --minimize-url -R argh -i e \
|
||||
$svnrepo/mirror/argh/a/b/c/d/e &&
|
||||
git-config svn.useSvmProps true &&
|
||||
git-svn fetch --all
|
||||
"
|
||||
|
||||
@@ -9,9 +9,9 @@ test_description='git-svn useSvnsyncProps test'
|
||||
|
||||
test_expect_success 'load svnsync repo' "
|
||||
svnadmin load -q $rawsvnrepo < ../t9111/svnsync.dump &&
|
||||
git-svn init -R arr -i bar $svnrepo/bar &&
|
||||
git-svn init -R argh -i dir $svnrepo/dir &&
|
||||
git-svn init -R argh -i e $svnrepo/dir/a/b/c/d/e &&
|
||||
git-svn init --minimize-url -R arr -i bar $svnrepo/bar &&
|
||||
git-svn init --minimize-url -R argh -i dir $svnrepo/dir &&
|
||||
git-svn init --minimize-url -R argh -i e $svnrepo/dir/a/b/c/d/e &&
|
||||
git-config svn.useSvnsyncProps true &&
|
||||
git-svn fetch --all
|
||||
"
|
||||
|
||||
@@ -26,8 +26,9 @@ perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
|
||||
unset GIT_DIR GIT_CONFIG
|
||||
WORKDIR=$(pwd)
|
||||
SERVERDIR=$(pwd)/gitcvs.git
|
||||
git_config="$SERVERDIR/config"
|
||||
CVSROOT=":fork:$SERVERDIR"
|
||||
CVSWORK=$(pwd)/cvswork
|
||||
CVSWORK="$(pwd)/cvswork"
|
||||
CVS_SERVER=git-cvsserver
|
||||
export CVSROOT CVS_SERVER
|
||||
|
||||
@@ -43,7 +44,7 @@ echo >empty &&
|
||||
# note that cvs doesn't accept absolute pathnames
|
||||
# as argument to co -d
|
||||
test_expect_success 'basic checkout' \
|
||||
'cvs -Q co -d cvswork master &&
|
||||
'GIT_CONFIG="$git_config" cvs -Q co -d cvswork master &&
|
||||
test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5))" = "empty/1.1/"'
|
||||
|
||||
test_expect_success 'cvs update (create new file)' \
|
||||
@@ -52,7 +53,7 @@ test_expect_success 'cvs update (create new file)' \
|
||||
git commit -q -m "Add testfile1" &&
|
||||
git push gitcvs.git >/dev/null &&
|
||||
cd cvswork &&
|
||||
cvs -Q update &&
|
||||
GIT_CONFIG="$git_config" cvs -Q update &&
|
||||
test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.1/" &&
|
||||
diff -q testfile1 ../testfile1'
|
||||
|
||||
@@ -63,7 +64,7 @@ test_expect_success 'cvs update (update existing file)' \
|
||||
git commit -q -m "Append to testfile1" &&
|
||||
git push gitcvs.git >/dev/null &&
|
||||
cd cvswork &&
|
||||
cvs -Q update &&
|
||||
GIT_CONFIG="$git_config" cvs -Q update &&
|
||||
test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.2/" &&
|
||||
diff -q testfile1 ../testfile1'
|
||||
|
||||
@@ -76,7 +77,7 @@ test_expect_failure "cvs update w/o -d doesn't create subdir (TODO)" \
|
||||
git commit -q -m "Single Subdirectory" &&
|
||||
git push gitcvs.git >/dev/null &&
|
||||
cd cvswork &&
|
||||
cvs -Q update &&
|
||||
GIT_CONFIG="$git_config" cvs -Q update &&
|
||||
test ! -d test'
|
||||
|
||||
cd "$WORKDIR"
|
||||
@@ -89,7 +90,7 @@ test_expect_success 'cvs update (subdirectories)' \
|
||||
git commit -q -m "deep sub directory structure" &&
|
||||
git push gitcvs.git >/dev/null &&
|
||||
cd cvswork &&
|
||||
cvs -Q update -d &&
|
||||
GIT_CONFIG="$git_config" cvs -Q update -d &&
|
||||
(for dir in A A/B A/B/C A/D E; do
|
||||
filename="file_in_$(echo $dir|sed -e "s#/# #g")" &&
|
||||
if test "$(echo $(grep -v ^D $dir/CVS/Entries|cut -d/ -f2,3,5))" = "$filename/1.1/" &&
|
||||
@@ -107,7 +108,7 @@ test_expect_success 'cvs update (delete file)' \
|
||||
git commit -q -m "Remove testfile1" &&
|
||||
git push gitcvs.git >/dev/null &&
|
||||
cd cvswork &&
|
||||
cvs -Q update &&
|
||||
GIT_CONFIG="$git_config" cvs -Q update &&
|
||||
test -z "$(grep testfile1 CVS/Entries)" &&
|
||||
test ! -f testfile1'
|
||||
|
||||
@@ -118,7 +119,7 @@ test_expect_success 'cvs update (re-add deleted file)' \
|
||||
git commit -q -m "Re-Add testfile1" &&
|
||||
git push gitcvs.git >/dev/null &&
|
||||
cd cvswork &&
|
||||
cvs -Q update &&
|
||||
GIT_CONFIG="$git_config" cvs -Q update &&
|
||||
test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.4/" &&
|
||||
diff -q testfile1 ../testfile1'
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ static inline int tree_entry_len(const char *name, const unsigned char *sha1)
|
||||
|
||||
void update_tree_entry(struct tree_desc *);
|
||||
void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size);
|
||||
const unsigned char *tree_entry_extract(struct tree_desc *, const char **, unsigned int *);
|
||||
|
||||
/* Helper function that does both of the above and returns true for success */
|
||||
int tree_entry(struct tree_desc *, struct name_entry *);
|
||||
|
||||
@@ -264,10 +264,12 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
|
||||
* directories, in case this unlink is the removal of the
|
||||
* last entry in the directory -- empty directories are removed.
|
||||
*/
|
||||
static void unlink_entry(char *name)
|
||||
static void unlink_entry(char *name, char *last_symlink)
|
||||
{
|
||||
char *cp, *prev;
|
||||
|
||||
if (has_symlink_leading_path(name, last_symlink))
|
||||
return;
|
||||
if (unlink(name))
|
||||
return;
|
||||
prev = NULL;
|
||||
@@ -291,11 +293,12 @@ static void unlink_entry(char *name)
|
||||
|
||||
static struct checkout state;
|
||||
static void check_updates(struct cache_entry **src, int nr,
|
||||
struct unpack_trees_options *o)
|
||||
struct unpack_trees_options *o)
|
||||
{
|
||||
unsigned short mask = htons(CE_UPDATE);
|
||||
unsigned cnt = 0, total = 0;
|
||||
struct progress progress;
|
||||
char last_symlink[PATH_MAX];
|
||||
|
||||
if (o->update && o->verbose_update) {
|
||||
for (total = cnt = 0; cnt < nr; cnt++) {
|
||||
@@ -309,6 +312,7 @@ static void check_updates(struct cache_entry **src, int nr,
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
*last_symlink = '\0';
|
||||
while (nr--) {
|
||||
struct cache_entry *ce = *src++;
|
||||
|
||||
@@ -317,13 +321,15 @@ static void check_updates(struct cache_entry **src, int nr,
|
||||
display_progress(&progress, ++cnt);
|
||||
if (!ce->ce_mode) {
|
||||
if (o->update)
|
||||
unlink_entry(ce->name);
|
||||
unlink_entry(ce->name, last_symlink);
|
||||
continue;
|
||||
}
|
||||
if (ce->ce_flags & mask) {
|
||||
ce->ce_flags &= ~mask;
|
||||
if (o->update)
|
||||
if (o->update) {
|
||||
checkout_entry(ce, &state, NULL);
|
||||
*last_symlink = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (total)
|
||||
|
||||
Reference in New Issue
Block a user