Compare commits
294 Commits
Author | SHA1 | Date | |
---|---|---|---|
93dcab2937 | |||
2a1ddc58e4 | |||
5e7bfe2567 | |||
5d318ce6a9 | |||
ae2b0f1518 | |||
e8cc80d039 | |||
f678dd180a | |||
3a2f2bb354 | |||
874fbc3323 | |||
2c52a42dd7 | |||
ee72aeaf00 | |||
a50b870aa1 | |||
9c20a47067 | |||
b7884981f8 | |||
30c7bb249e | |||
073dab137a | |||
fbf8ac212c | |||
b99a394cd1 | |||
c61642185d | |||
d1ab157759 | |||
2b6e34c1a3 | |||
60435f68bb | |||
bb931cf9d7 | |||
302ebfe521 | |||
c7d77dab93 | |||
9ce392f482 | |||
07f9247722 | |||
c3df856842 | |||
d6ebd2590c | |||
1b1480ff6a | |||
f35230fb11 | |||
ef07618fdd | |||
b17e659dd4 | |||
3dd94e3b2e | |||
e814bc4d15 | |||
f801477645 | |||
ce335fe04f | |||
4dbd135279 | |||
aa7f412abf | |||
9f70b80692 | |||
88b5a74883 | |||
60abce3c0f | |||
924215024c | |||
e0a87193d3 | |||
936a23420c | |||
3d32051f4f | |||
bd22c904a0 | |||
757f17bca5 | |||
8fc66df237 | |||
f98d863d21 | |||
a6322d079b | |||
9ae2172aed | |||
f6e2869f48 | |||
13cfdfd5fa | |||
4ddba79db7 | |||
7b5d895da6 | |||
faea9ccbad | |||
8d63013291 | |||
0870ca7fab | |||
54f4b87454 | |||
942c1f53ae | |||
2d2465c015 | |||
1b1e59c508 | |||
10bea152a3 | |||
0890098780 | |||
11979b98ad | |||
7b89996749 | |||
acf59575ca | |||
5e3a769186 | |||
e388ab74db | |||
29508e1efb | |||
80e21a9ed8 | |||
397c76697f | |||
22a06b3c47 | |||
6ed64058e1 | |||
a4caa52140 | |||
e3fe532ddc | |||
fd913b3910 | |||
e246483dc5 | |||
36a7cad6e4 | |||
3eeb419968 | |||
52b6536c62 | |||
0b4276931f | |||
7f59dbbb8f | |||
eb777612f0 | |||
f9039f30d5 | |||
9a888b758f | |||
06a45c8cc9 | |||
62af0b532b | |||
4d16f8de16 | |||
0cb022e052 | |||
2e67a5f449 | |||
a8aca418d6 | |||
583122cd1b | |||
3afd169480 | |||
c3e24a7d46 | |||
6eb668df76 | |||
087b6742fc | |||
6b7b042772 | |||
751a71e2b5 | |||
0adb3358f6 | |||
d2ac1cd263 | |||
3200d1aee0 | |||
a575603af2 | |||
fee3365fe1 | |||
1e9eb2e937 | |||
f30c95dd76 | |||
3c07b1d194 | |||
22ff00fc8b | |||
9b626e752e | |||
a7fb51d3d4 | |||
27dedf0c3b | |||
a8883288fa | |||
fbba222f5d | |||
80b1e511d7 | |||
011f4274bb | |||
0c15cc921a | |||
92927ed0aa | |||
5b4525eb8b | |||
8b3fbeef39 | |||
ebdbfa8b55 | |||
0ff2ce9d8a | |||
565cb99114 | |||
8366a10ab2 | |||
c0c35d5e41 | |||
7dbc2c0402 | |||
ad4f4daae8 | |||
a0fa2a10b4 | |||
1a41e743c6 | |||
97fc6c5fba | |||
cb22bc4447 | |||
8e49d50388 | |||
c0bbbb1ba9 | |||
3299c6f6a8 | |||
f8348be3be | |||
4a4e6fd74f | |||
545f229a4b | |||
a52e4ef877 | |||
cd0a781c38 | |||
313c4714c5 | |||
bce8230d5d | |||
8b649e27dd | |||
60d64db461 | |||
d7bba81575 | |||
08db81a9f1 | |||
7acab8f167 | |||
2db0bfbc04 | |||
b2309b7019 | |||
9add69b1b1 | |||
232475d382 | |||
2ed02887bd | |||
d4072c9722 | |||
b6ebac9e43 | |||
0f3f5e3f69 | |||
1331df8781 | |||
b0c698a6e4 | |||
94d2331770 | |||
6d5410d651 | |||
4b1ca25e42 | |||
0086e2c854 | |||
abacbe4166 | |||
ac0b86dadf | |||
ba1dbb61ea | |||
8614e92323 | |||
54a9ba0d44 | |||
acc075a8ad | |||
ceae78b438 | |||
f7a2eb7359 | |||
7765e7ebda | |||
e6bd23911e | |||
07203659d0 | |||
04e7ca1a1b | |||
d7b1a1ddbe | |||
1c3039e8f1 | |||
9bc0f32c77 | |||
b4ad3552de | |||
5231148202 | |||
2a444781b1 | |||
c283ab21c1 | |||
fd66dbf529 | |||
e433705dd4 | |||
cb93c19365 | |||
f7d24bbefb | |||
6fd72e39af | |||
e9af60c88b | |||
857f26d2f4 | |||
46e651743a | |||
5f3aa197ac | |||
3cab3594e9 | |||
631ba30907 | |||
4bc51db0fe | |||
6b209d4733 | |||
9ce7028531 | |||
53de71f88b | |||
9e5f4a5539 | |||
ed9a540b2b | |||
592ee97d8f | |||
7f10f7c4e4 | |||
0879aa2870 | |||
0867b0125a | |||
f84f9d38eb | |||
0e9ab02da7 | |||
601c978c1b | |||
17cf939724 | |||
ff56fe1ca7 | |||
e3e291fc07 | |||
605607cc62 | |||
66c9ec2555 | |||
ad7db62113 | |||
14df4c4188 | |||
23ea3e201c | |||
a1c292958f | |||
13956670a7 | |||
a489352e3d | |||
68afd5fab7 | |||
ff36de0847 | |||
c44922a781 | |||
186f855fc6 | |||
c8a4f5e542 | |||
e09f5d7b07 | |||
f37d0cc3ff | |||
f4f440a039 | |||
61f81518a2 | |||
23fc63bf8f | |||
cb34882bd6 | |||
f8d294f0a4 | |||
5ca15b8af7 | |||
7d4de59b17 | |||
f3ad062560 | |||
01d4f0e775 | |||
a16db4f472 | |||
109fc2b97b | |||
8168373fe7 | |||
c2c07a5c2a | |||
cbce5d8961 | |||
fcfa32b9e1 | |||
4bfb6b62ff | |||
39b4ac9968 | |||
76bca9d1a9 | |||
f2416c27ef | |||
d0fde471ab | |||
df8171ccb3 | |||
067744bd5d | |||
fb612d54c1 | |||
b2d09f063a | |||
77131db585 | |||
390cb0c17a | |||
a5ae8e64cf | |||
79f6ac77d9 | |||
d1745afa2f | |||
52963a7a3f | |||
92e2eb9c0a | |||
0dd276b871 | |||
5e0306adfa | |||
e66ab03fcf | |||
31b9755a65 | |||
7141b3b780 | |||
44760f1d55 | |||
93d69d8691 | |||
72e5890b68 | |||
90279074ca | |||
67ffdf4c0a | |||
bee8e79da0 | |||
95d117b605 | |||
f179044862 | |||
fcbc3083e3 | |||
0cfddacdcc | |||
bb73d73c08 | |||
3402f1d6a3 | |||
4ea836dba9 | |||
75187c9deb | |||
26349b2e5e | |||
0772b9a633 | |||
c17fb6ee07 | |||
58e60dd203 | |||
c0a2ed1b49 | |||
9eba845f20 | |||
54c2533da0 | |||
d071e8dbb6 | |||
12aa7456c9 | |||
9e5d2b4096 | |||
4607166d07 | |||
b748421aaa | |||
b52d9f9ba7 | |||
d5bc7eecbb | |||
cfd8aefd4b | |||
00d8bbd3c4 | |||
25a67553ea | |||
a61399b5fb | |||
990f856a62 | |||
d6179f56f8 | |||
089f20dce1 | |||
9f25c7bd5c | |||
dc4393cba3 |
8
.gitignore
vendored
8
.gitignore
vendored
@ -19,6 +19,7 @@ git-commit
|
||||
git-commit-tree
|
||||
git-convert-objects
|
||||
git-count-objects
|
||||
git-cvsexportcommit
|
||||
git-cvsimport
|
||||
git-daemon
|
||||
git-diff
|
||||
@ -36,10 +37,12 @@ git-get-tar-commit-id
|
||||
git-grep
|
||||
git-hash-object
|
||||
git-http-fetch
|
||||
git-http-push
|
||||
git-index-pack
|
||||
git-init-db
|
||||
git-local-fetch
|
||||
git-log
|
||||
git-lost-found
|
||||
git-ls-files
|
||||
git-ls-remote
|
||||
git-ls-tree
|
||||
@ -58,6 +61,7 @@ git-mktag
|
||||
git-name-rev
|
||||
git-mv
|
||||
git-octopus
|
||||
git-pack-redundant
|
||||
git-pack-objects
|
||||
git-parse-remote
|
||||
git-patch-id
|
||||
@ -70,8 +74,8 @@ git-read-tree
|
||||
git-rebase
|
||||
git-receive-pack
|
||||
git-relink
|
||||
git-rename
|
||||
git-repack
|
||||
git-repo-config
|
||||
git-request-pull
|
||||
git-reset
|
||||
git-resolve
|
||||
@ -107,6 +111,8 @@ git-verify-tag
|
||||
git-whatchanged
|
||||
git-write-tree
|
||||
git-core-*/?*
|
||||
test-date
|
||||
test-delta
|
||||
*.tar.gz
|
||||
*.dsc
|
||||
*.deb
|
||||
|
1
Documentation/.gitignore
vendored
1
Documentation/.gitignore
vendored
@ -3,3 +3,4 @@
|
||||
*.1
|
||||
*.7
|
||||
howto-index.txt
|
||||
doc.dep
|
||||
|
@ -49,22 +49,22 @@ install: man
|
||||
$(INSTALL) $(DOC_MAN1) $(DESTDIR)/$(man1)
|
||||
$(INSTALL) $(DOC_MAN7) $(DESTDIR)/$(man7)
|
||||
|
||||
# 'include' dependencies
|
||||
$(patsubst %.txt,%.1,$(wildcard git-diff-*.txt)): \
|
||||
diff-format.txt diff-options.txt
|
||||
$(patsubst %.txt,%.html,$(wildcard git-diff-*.txt)): \
|
||||
diff-format.txt diff-options.txt
|
||||
|
||||
$(patsubst %,%.1,git-fetch git-pull git-push): pull-fetch-param.txt
|
||||
$(patsubst %,%.html,git-fetch git-pull git-push): pull-fetch-param.txt
|
||||
#
|
||||
# Determine "include::" file references in asciidoc files.
|
||||
#
|
||||
doc.dep : $(wildcard *.txt) build-docdep.perl
|
||||
rm -f $@+ $@
|
||||
perl ./build-docdep.perl >$@+
|
||||
mv $@+ $@
|
||||
|
||||
$(patsubst %,%.1,git-merge git-pull): merge-pull-opts.txt
|
||||
$(patsubst %,%.html,git-merge git-pull): merge-pull-opts.txt
|
||||
-include doc.dep
|
||||
|
||||
git.7: ../README
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html
|
||||
rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep
|
||||
|
||||
%.html : %.txt
|
||||
asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<
|
||||
|
50
Documentation/build-docdep.perl
Executable file
50
Documentation/build-docdep.perl
Executable file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
my %include = ();
|
||||
my %included = ();
|
||||
|
||||
for my $text (<*.txt>) {
|
||||
open I, '<', $text || die "cannot read: $text";
|
||||
while (<I>) {
|
||||
if (/^include::/) {
|
||||
chomp;
|
||||
s/^include::\s*//;
|
||||
s/\[\]//;
|
||||
$include{$text}{$_} = 1;
|
||||
$included{$_} = 1;
|
||||
}
|
||||
}
|
||||
close I;
|
||||
}
|
||||
|
||||
# Do we care about chained includes???
|
||||
my $changed = 1;
|
||||
while ($changed) {
|
||||
$changed = 0;
|
||||
while (my ($text, $included) = each %include) {
|
||||
for my $i (keys %$included) {
|
||||
# $text has include::$i; if $i includes $j
|
||||
# $text indirectly includes $j.
|
||||
if (exists $include{$i}) {
|
||||
for my $j (keys %{$include{$i}}) {
|
||||
if (!exists $include{$text}{$j}) {
|
||||
$include{$text}{$j} = 1;
|
||||
$included{$j} = 1;
|
||||
$changed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (my ($text, $included) = each %include) {
|
||||
if (! exists $included{$text} &&
|
||||
(my $base = $text) =~ s/\.txt$//) {
|
||||
my ($suffix) = '1';
|
||||
if ($base eq 'git') {
|
||||
$suffix = '7'; # yuck...
|
||||
}
|
||||
print "$base.html $base.$suffix : ", join(" ", keys %$included), "\n";
|
||||
}
|
||||
}
|
@ -8,13 +8,13 @@ git-diff-index <tree-ish>::
|
||||
compares the <tree-ish> and the files on the filesystem.
|
||||
|
||||
git-diff-index --cached <tree-ish>::
|
||||
compares the <tree-ish> and the cache.
|
||||
compares the <tree-ish> and the index.
|
||||
|
||||
git-diff-tree [-r] <tree-ish-1> <tree-ish-2> [<pattern>...]::
|
||||
compares the trees named by the two arguments.
|
||||
|
||||
git-diff-files [<pattern>...]::
|
||||
compares the cache and the files on the filesystem.
|
||||
compares the index and the files on the filesystem.
|
||||
|
||||
|
||||
An output line is formatted this way:
|
||||
@ -47,7 +47,7 @@ That is, from the left to the right:
|
||||
. an LF or a NUL when '-z' option is used, to terminate the record.
|
||||
|
||||
<sha1> is shown as all 0's if a file is new on the filesystem
|
||||
and it is out of sync with the cache.
|
||||
and it is out of sync with the index.
|
||||
|
||||
Example:
|
||||
|
||||
@ -81,7 +81,7 @@ The "diff" formatting options can be customized via the
|
||||
environment variable 'GIT_DIFF_OPTS'. For example, if you
|
||||
prefer context diff:
|
||||
|
||||
GIT_DIFF_OPTS=-c git-diff-index -p $(cat .git/HEAD)
|
||||
GIT_DIFF_OPTS=-c git-diff-index -p HEAD
|
||||
|
||||
|
||||
2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the
|
||||
@ -104,7 +104,7 @@ where:
|
||||
The file parameters can point at the user's working file
|
||||
(e.g. `new-file` in "git-diff-files"), `/dev/null` (e.g. `old-file`
|
||||
when a new file is added), or a temporary file (e.g. `old-file` in the
|
||||
cache). 'GIT_EXTERNAL_DIFF' should not worry about unlinking the
|
||||
index). 'GIT_EXTERNAL_DIFF' should not worry about unlinking the
|
||||
temporary file --- it is removed when 'GIT_EXTERNAL_DIFF' exits.
|
||||
|
||||
For a path that is unmerged, 'GIT_EXTERNAL_DIFF' is called with 1
|
||||
|
@ -13,6 +13,11 @@
|
||||
--name-status::
|
||||
Show only names and status of changed files.
|
||||
|
||||
--full-index::
|
||||
Instead of the first handful characters, show full
|
||||
object name of pre- and post-image blob on the "index"
|
||||
line when generating a patch format output.
|
||||
|
||||
-B::
|
||||
Break complete rewrite changes into pairs of delete and create.
|
||||
|
||||
@ -50,7 +55,7 @@
|
||||
<orderfile>, which has one shell glob pattern per line.
|
||||
|
||||
-R::
|
||||
Swap two inputs; that is, show differences from cache or
|
||||
Swap two inputs; that is, show differences from index or
|
||||
on-disk file to tree contents.
|
||||
|
||||
For more detailed explanation on these common options, see also
|
||||
|
19
Documentation/fetch-options.txt
Normal file
19
Documentation/fetch-options.txt
Normal file
@ -0,0 +1,19 @@
|
||||
-a, \--append::
|
||||
Append ref names and object names of fetched refs to the
|
||||
existing contents of `.git/FETCH_HEAD`. Without this
|
||||
option old data in `.git/FETCH_HEAD` will be overwritten.
|
||||
|
||||
-f, \--force::
|
||||
|
||||
-t, \--tags::
|
||||
By default, the git core utilities will not fetch and store
|
||||
tags under the same name as the remote repository; ask it
|
||||
to do so using `--tags`. Using this option will bound the
|
||||
list of objects pulled to the remote tags. Commits in branches
|
||||
beyond the tags will be ignored.
|
||||
|
||||
-u, \--update-head-ok::
|
||||
By default `git-fetch` refuses to update the head which
|
||||
corresponds to the current branch. This flag disables the
|
||||
check. Note that fetching into the current branch will not
|
||||
update the index and working directory, so use it with care.
|
@ -8,8 +8,8 @@ git-am - Apply a series of patches in a mailbox
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-am' [--signoff] [--dotest=<dir>] [--utf8] [--3way] <mbox>...
|
||||
'git-am' [--skip]
|
||||
'git-am' [--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way] <mbox>...
|
||||
'git-am' [--skip | --resolved]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -31,6 +31,10 @@ OPTIONS
|
||||
Pass `--utf8` and `--keep` flags to `git-mailinfo` (see
|
||||
gitlink:git-mailinfo[1]).
|
||||
|
||||
--binary::
|
||||
Pass `--allow-binary-replacement` flag to `git-apply`
|
||||
(see gitlink:git-apply[1]).
|
||||
|
||||
--3way::
|
||||
When the patch does not apply cleanly, fall back on
|
||||
3-way merge, if the patch records the identity of blobs
|
||||
@ -44,6 +48,13 @@ OPTIONS
|
||||
--interactive::
|
||||
Run interactively, just like git-applymbox.
|
||||
|
||||
--resolved::
|
||||
After a patch failure (e.g. attempting to apply
|
||||
conflicting patch), the user has applied it by hand and
|
||||
the index file stores the result of the application.
|
||||
Make a commit using the authorship and commit log
|
||||
extracted from the e-mail message and the current index
|
||||
file, and continue.
|
||||
|
||||
DISCUSSION
|
||||
----------
|
||||
@ -56,12 +67,9 @@ recover from this in one of two ways:
|
||||
. skip the current one by re-running the command with '--skip'
|
||||
option.
|
||||
|
||||
. hand resolve the conflict in the working directory, run 'git
|
||||
diff HEAD' to extract the merge result into a patch form and
|
||||
replacing the patch in .dotest/patch file. After doing this,
|
||||
run `git-reset --hard HEAD` to bring the working tree to the
|
||||
state before half-applying the patch, then re-run the command
|
||||
without any options.
|
||||
. hand resolve the conflict in the working directory, and update
|
||||
the index file to bring it in a state that the patch should
|
||||
have produced. Then run the command with '--resume' option.
|
||||
|
||||
The command refuses to process new mailboxes while `.dotest`
|
||||
directory exists, so if you decide to start over from scratch,
|
||||
|
@ -8,7 +8,7 @@ git-apply - Apply patch on a git index file and a work tree
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--index-info] [-z] [<patch>...]
|
||||
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [<patch>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -72,6 +72,23 @@ OPTIONS
|
||||
patch. Give this flag after those flags to also apply
|
||||
the patch.
|
||||
|
||||
--no-add::
|
||||
When applying a patch, ignore additions made by the
|
||||
patch. This can be used to extract common part between
|
||||
two files by first running `diff` on them and applying
|
||||
the result with this option, which would apply the
|
||||
deletion part but not addition part.
|
||||
|
||||
--allow-binary-replacement::
|
||||
When applying a patch, which is a git-enhanced patch
|
||||
that was prepared to record the pre- and post-image object
|
||||
name in full, and the path being patched exactly matches
|
||||
the object the patch applies to (i.e. "index" line's
|
||||
pre-image object name is what is in the working tree),
|
||||
and the post-image object is available in the object
|
||||
database, use the post-image object as the patch
|
||||
result. This allows binary files to be patched in a
|
||||
very limited way.
|
||||
|
||||
Author
|
||||
------
|
||||
|
@ -3,11 +3,11 @@ git-branch(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-branch - Create a new branch.
|
||||
git-branch - Create a new branch, or remove an old one.
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-branch' [<branchname> [start-point]]
|
||||
'git-branch' [-d | -D] [<branchname> [start-point]]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -19,11 +19,18 @@ created, otherwise it will be created at the current HEAD.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-d::
|
||||
Delete a branch. The branch must be fully merged.
|
||||
|
||||
-D::
|
||||
Delete a branch irrespective of its index status.
|
||||
|
||||
<branchname>::
|
||||
The name of the branch to create.
|
||||
The name of the branch to create or delete.
|
||||
|
||||
start-point::
|
||||
Where to create the branch; defaults to HEAD.
|
||||
Where to create the branch; defaults to HEAD. This
|
||||
option has no meaning with -d and -D.
|
||||
|
||||
Author
|
||||
------
|
||||
|
@ -3,7 +3,7 @@ git-checkout-index(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-checkout-index - Copy files from the cache to the working directory
|
||||
git-checkout-index - Copy files from the index to the working directory
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@ -13,26 +13,26 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Will copy all files listed from the cache to the working directory
|
||||
Will copy all files listed from the index to the working directory
|
||||
(not overwriting existing files).
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-u::
|
||||
-u|--index::
|
||||
update stat information for the checked out entries in
|
||||
the cache file.
|
||||
the index file.
|
||||
|
||||
-q::
|
||||
be quiet if files exist or are not in the cache
|
||||
-q|--quiet::
|
||||
be quiet if files exist or are not in the index
|
||||
|
||||
-f::
|
||||
-f|--force::
|
||||
forces overwrite of existing files
|
||||
|
||||
-a::
|
||||
checks out all files in the cache. Cannot be used
|
||||
-a|--all::
|
||||
checks out all files in the index. Cannot be used
|
||||
together with explicit filenames.
|
||||
|
||||
-n::
|
||||
-n|--no-create::
|
||||
Don't checkout new files, only refresh files already checked
|
||||
out.
|
||||
|
||||
@ -57,7 +57,7 @@ supposed to be able to do things like:
|
||||
|
||||
which will force all existing `*.h` files to be replaced with their
|
||||
cached copies. If an empty command line implied "all", then this would
|
||||
force-refresh everything in the cache, which was not the point.
|
||||
force-refresh everything in the index, which was not the point.
|
||||
|
||||
To update and refresh only the files already checked out:
|
||||
|
||||
@ -74,7 +74,7 @@ desired tree into the index, and do a
|
||||
|
||||
git-checkout-index --prefix=git-export-dir/ -a
|
||||
|
||||
and git-checkout-index will "export" the cache into the specified
|
||||
and git-checkout-index will "export" the index into the specified
|
||||
directory.
|
||||
|
||||
NOTE The final "/" is important. The exported name is literally just
|
||||
|
@ -8,11 +8,26 @@ git-clone - Clones a repository.
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-clone' [-l [-s]] [-q] [-n] [-u <upload-pack>] <repository> <directory>
|
||||
'git-clone' [-l [-s]] [-q] [-n] [-u <upload-pack>] <repository> [<directory>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Clones a repository into a newly created directory.
|
||||
Clones a repository into a newly created directory. All remote
|
||||
branch heads are copied under `$GIT_DIR/refs/heads/`, except
|
||||
that the remote `master` is also copied to `origin` branch.
|
||||
|
||||
In addition, `$GIT_DIR/remotes/origin` file is set up to have
|
||||
this line:
|
||||
|
||||
Pull: master:origin
|
||||
|
||||
This is to help the typical workflow of working off of the
|
||||
remote `master` branch. Every time `git pull` without argument
|
||||
is run, the progress on the remote `master` branch is tracked by
|
||||
copying it into the local `origin` branch, and merged into the
|
||||
branch you are currently working on. Remote branches other than
|
||||
`master` are also added there to be tracked.
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
@ -28,9 +43,10 @@ OPTIONS
|
||||
--shared::
|
||||
-s::
|
||||
When the repository to clone is on the local machine,
|
||||
instead of using hard links automatically setup
|
||||
instead of using hard links, automatically setup
|
||||
.git/objects/info/alternatives to share the objects
|
||||
with the source repository
|
||||
with the source repository. The resulting repository
|
||||
starts out without any object of its own.
|
||||
|
||||
--quiet::
|
||||
-q::
|
||||
@ -49,13 +65,14 @@ OPTIONS
|
||||
|
||||
<repository>::
|
||||
The (possibly remote) repository to clone from. It can
|
||||
be an "rsync://host/dir" URL, an "http://host/dir" URL,
|
||||
or [<host>:]/dir notation that is used by 'git-clone-pack'.
|
||||
Currently http transport is not supported.
|
||||
be any URL git-fetch supports.
|
||||
|
||||
<directory>::
|
||||
The name of a new directory to be cloned into. It is an
|
||||
error to specify an existing directory.
|
||||
The name of a new directory to clone into. The "humanish"
|
||||
part of the source repository is used if no directory is
|
||||
explicitly given ("repo" for "/path/to/repo.git" and "foo"
|
||||
for "host.xz:foo/.git"). Cloning into an existing directory
|
||||
is not allowed.
|
||||
|
||||
Author
|
||||
------
|
||||
@ -63,7 +80,7 @@ Written by Linus Torvalds <torvalds@osdl.org>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by Junio C Hamano.
|
||||
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
||||
|
||||
|
||||
GIT
|
||||
|
@ -8,7 +8,7 @@ git-commit-tree - Creates a new commit object
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-commit-tree' <tree> [-p <parent commit>]\ < changelog
|
||||
'git-commit-tree' <tree> [-p <parent commit>]\* < changelog
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -26,8 +26,9 @@ to get there.
|
||||
|
||||
Normally a commit would identify a new "HEAD" state, and while git
|
||||
doesn't care where you save the note about that state, in practice we
|
||||
tend to just write the result to the file `.git/HEAD`, so that we can
|
||||
always see what the last committed state was.
|
||||
tend to just write the result to the file that is pointed at by
|
||||
`.git/HEAD`, so that we can always see what the last committed
|
||||
state was.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
56
Documentation/git-cvsexportcommit.txt
Normal file
56
Documentation/git-cvsexportcommit.txt
Normal file
@ -0,0 +1,56 @@
|
||||
git-cvsexportcommit(1)
|
||||
======================
|
||||
|
||||
NAME
|
||||
----
|
||||
git-cvsexportcommit - Export a commit to a CVS checkout
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
git-cvsapplycommmit.perl
|
||||
[ -h ] [ -v ] [ -c ] [ -p ] [PARENTCOMMIT] COMMITID
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Exports a commit from GIT to a CVS checkout, making it easier
|
||||
to merge patches from a git repository into a CVS repository.
|
||||
|
||||
Execute it from the root of the CVS working copy. GIT_DIR must be defined.
|
||||
|
||||
It does its best to do the safe thing, it will check that the files are
|
||||
unchanged and up to date in the CVS checkout, and it will not autocommit
|
||||
by default.
|
||||
|
||||
Supports file additions, removals, and commits that affect binary files.
|
||||
|
||||
If the commit is a merge commit, you must tell git-cvsapplycommit what parent
|
||||
should the changeset be done against.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
-c::
|
||||
Commit automatically if the patch applied cleanly. It will not
|
||||
commit if any hunks fail to apply or there were other problems.
|
||||
|
||||
-p::
|
||||
Be pedantic (paranoid) when applying patches. Invokes patch with
|
||||
--fuzz=0
|
||||
|
||||
-v::
|
||||
Verbose.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Martin Langhoff <martin@catalyst.net.nz>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by Martin Langhoff <martin@catalyst.net.nz>
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the gitlink:git[7] suite
|
||||
|
@ -35,7 +35,7 @@ OPTIONS
|
||||
|
||||
-i::
|
||||
Import-only: don't perform a checkout after importing. This option
|
||||
ensures the working directory and cache remain untouched and will
|
||||
ensures the working directory and index remain untouched and will
|
||||
not create them if they do not exist.
|
||||
|
||||
-k::
|
||||
|
@ -8,7 +8,7 @@ git-daemon - A really simple server for git repositories.
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
|
||||
[--timeout=n] [--init-timeout=n] [directory...]
|
||||
[--timeout=n] [--init-timeout=n] [--strict-paths] [directory...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -29,13 +29,19 @@ This is ideally suited for read-only updates, ie pulling from git repositories.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
--strict-paths::
|
||||
Match paths exactly (i.e. don't allow "/foo/repo" when the real path is
|
||||
"/foo/repo.git" or "/foo/repo/.git") and don't do user-relative paths.
|
||||
git-daemon will refuse to start when this option is enabled and no
|
||||
whitelist is specified.
|
||||
|
||||
--export-all::
|
||||
Allow pulling from all directories that look like GIT repositories
|
||||
(have the 'objects' subdirectory and a 'HEAD' file), even if they
|
||||
(have the 'objects' and 'refs' subdirectories), even if they
|
||||
do not have the 'git-daemon-export-ok' file.
|
||||
|
||||
--inetd::
|
||||
Have the server run as an inetd service.
|
||||
Have the server run as an inetd service. Implies --syslog.
|
||||
|
||||
--port::
|
||||
Listen on an alternative port.
|
||||
@ -57,9 +63,15 @@ OPTIONS
|
||||
--verbose::
|
||||
Log details about the incoming connections and requested files.
|
||||
|
||||
<directory>::
|
||||
A directory to add to the whitelist of allowed directories. Unless
|
||||
--strict-paths is specified this will also include subdirectories
|
||||
of each named directory.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
|
||||
Written by Linus Torvalds <torvalds@osdl.org>, YOSHIFUJI Hideaki
|
||||
<yoshfuji@linux-ipv6.org> and the git-list <git@vger.kernel.org>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
@ -3,7 +3,7 @@ git-diff-files(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-diff-files - Compares files in the working tree and the cache
|
||||
git-diff-files - Compares files in the working tree and the index
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@ -12,9 +12,9 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Compares the files in the working tree and the cache. When paths
|
||||
Compares the files in the working tree and the index. When paths
|
||||
are specified, compares only those named paths. Otherwise all
|
||||
entries in the cache are compared. The output format is the
|
||||
entries in the index are compared. The output format is the
|
||||
same as "git-diff-index" and "git-diff-tree".
|
||||
|
||||
OPTIONS
|
||||
|
@ -3,7 +3,7 @@ git-diff-index(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-diff-index - Compares content and mode of blobs between the cache and repository
|
||||
git-diff-index - Compares content and mode of blobs between the index and repository
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@ -13,10 +13,10 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Compares the content and mode of the blobs found via a tree
|
||||
object with the content of the current cache and, optionally
|
||||
object with the content of the current index and, optionally
|
||||
ignoring the stat state of the file on disk. When paths are
|
||||
specified, compares only those named paths. Otherwise all
|
||||
entries in the cache are compared.
|
||||
entries in the index are compared.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
@ -49,22 +49,22 @@ Cached Mode
|
||||
-----------
|
||||
If '--cached' is specified, it allows you to ask:
|
||||
|
||||
show me the differences between HEAD and the current cache
|
||||
show me the differences between HEAD and the current index
|
||||
contents (the ones I'd write with a "git-write-tree")
|
||||
|
||||
For example, let's say that you have worked on your working directory, updated
|
||||
some files in the cache and are ready to commit. You want to see eactly
|
||||
some files in the index and are ready to commit. You want to see eactly
|
||||
*what* you are going to commit is without having to write a new tree
|
||||
object and compare it that way, and to do that, you just do
|
||||
|
||||
git-diff-index --cached $(cat .git/HEAD)
|
||||
git-diff-index --cached HEAD
|
||||
|
||||
Example: let's say I had renamed `commit.c` to `git-commit.c`, and I had
|
||||
done an "git-update-index" to make that effective in the index file.
|
||||
"git-diff-files" wouldn't show anything at all, since the index file
|
||||
matches my working directory. But doing a "git-diff-index" does:
|
||||
|
||||
torvalds@ppc970:~/git> git-diff-index --cached $(cat .git/HEAD)
|
||||
torvalds@ppc970:~/git> git-diff-index --cached HEAD
|
||||
-100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 commit.c
|
||||
+100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 git-commit.c
|
||||
|
||||
@ -92,13 +92,13 @@ which is obviously a very useful question too, since that tells you what
|
||||
you *could* commit. Again, the output matches the "git-diff-tree -r"
|
||||
output to a tee, but with a twist.
|
||||
|
||||
The twist is that if some file doesn't match the cache, we don't have
|
||||
The twist is that if some file doesn't match the index, we don't have
|
||||
a backing store thing for it, and we use the magic "all-zero" sha1 to
|
||||
show that. So let's say that you have edited `kernel/sched.c`, but
|
||||
have not actually done a "git-update-index" on it yet - there is no
|
||||
"object" associated with the new state, and you get:
|
||||
|
||||
torvalds@ppc970:~/v2.6/linux> git-diff-index $(cat .git/HEAD )
|
||||
torvalds@ppc970:~/v2.6/linux> git-diff-index HEAD
|
||||
*100644->100664 blob 7476bb......->000000...... kernel/sched.c
|
||||
|
||||
ie it shows that the tree has changed, and that `kernel/sched.c` has is
|
||||
@ -110,7 +110,7 @@ NOTE: As with other commands of this type, "git-diff-index" does not
|
||||
actually look at the contents of the file at all. So maybe
|
||||
`kernel/sched.c` hasn't actually changed, and it's just that you
|
||||
touched it. In either case, it's a note that you need to
|
||||
"git-upate-cache" it to make the cache be in sync.
|
||||
"git-upate-index" it to make the index be in sync.
|
||||
|
||||
NOTE: You can have a mixture of files show up as "has been updated"
|
||||
and "is still dirty in the working directory" together. You can always
|
||||
|
@ -8,7 +8,7 @@ git-diff-tree - Compares the content and mode of blobs found via two tree object
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-diff-tree' [--stdin] [-m] [-s] [-v] [--pretty] [-t] [-r] [--root] [<common diff options>] <tree-ish> [<tree-ish>] [<path>...]
|
||||
'git-diff-tree' [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty] [-t] [-r] [--root] [<common diff options>] <tree-ish> [<tree-ish>] [<path>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -74,6 +74,10 @@ separated with a single space are given.
|
||||
commit message. Without "=<style>", it defaults to
|
||||
medium.
|
||||
|
||||
--no-commit-id::
|
||||
git-diff-tree outputs a line with the commit ID when
|
||||
applicable. This flag suppressed the commit ID output.
|
||||
|
||||
|
||||
Limiting Output
|
||||
---------------
|
||||
|
@ -8,7 +8,7 @@ git-fetch - Download objects and a head from another repository.
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-fetch' <repository> <refspec>...
|
||||
'git-fetch' <options> <repository> <refspec>...
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
@ -17,24 +17,16 @@ Fetches named heads or tags from another repository, along with
|
||||
the objects necessary to complete them.
|
||||
|
||||
The ref names and their object names of fetched refs are stored
|
||||
in $GIT_DIR/FETCH_HEAD. This information is left for a later merge
|
||||
in `.git/FETCH_HEAD`. This information is left for a later merge
|
||||
operation done by "git resolve" or "git octopus".
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
include::fetch-options.txt[]
|
||||
|
||||
include::pull-fetch-param.txt[]
|
||||
|
||||
-a, \--append::
|
||||
Append ref names and object names of fetched refs to the
|
||||
existing contents of $GIT_DIR/FETCH_HEAD. Without this
|
||||
option old data in $GIT_DIR/FETCH_HEAD will be overwritten.
|
||||
|
||||
-u, \--update-head-ok::
|
||||
By default 'git-fetch' refuses to update the head which
|
||||
corresponds to the current branch. This flag disables the
|
||||
check. Note that fetching into the current branch will not
|
||||
update the index and working directory, so use it with care.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
|
@ -33,7 +33,7 @@ index file and all SHA1 references in .git/refs/* as heads.
|
||||
Report tags.
|
||||
|
||||
--cache::
|
||||
Consider any object recorded in the cache also as a head node for
|
||||
Consider any object recorded in the index also as a head node for
|
||||
an unreachability trace.
|
||||
|
||||
--standalone::
|
||||
@ -68,7 +68,7 @@ that aren't readable from any of the specified head nodes.
|
||||
|
||||
So for example
|
||||
|
||||
git-fsck-objects --unreachable $(cat .git/HEAD .git/refs/heads/*)
|
||||
git-fsck-objects --unreachable HEAD $(cat .git/refs/heads/*)
|
||||
|
||||
will do quite a _lot_ of verification on the tree. There are a few
|
||||
extra validity tests to be added (make sure that tree objects are
|
||||
@ -125,7 +125,7 @@ GIT_OBJECT_DIRECTORY::
|
||||
used to specify the object database root (usually $GIT_DIR/objects)
|
||||
|
||||
GIT_INDEX_FILE::
|
||||
used to specify the index file of the cache
|
||||
used to specify the index file of the index
|
||||
|
||||
GIT_ALTERNATE_OBJECT_DIRECTORIES::
|
||||
used to specify additional object database roots (usually unset)
|
||||
|
@ -16,7 +16,7 @@ Computes the object ID value for an object with specified type
|
||||
with the contents of the named file (which can be outside of the
|
||||
work tree), and optionally writes the resulting object into the
|
||||
object database. Reports its object ID to its standard output.
|
||||
This is used by "git-cvsimport" to update the cache
|
||||
This is used by "git-cvsimport" to update the index
|
||||
without modifying files in the work tree. When <type> is not
|
||||
specified, it defaults to "blob".
|
||||
|
||||
|
89
Documentation/git-http-push.txt
Normal file
89
Documentation/git-http-push.txt
Normal file
@ -0,0 +1,89 @@
|
||||
git-http-push(1)
|
||||
================
|
||||
|
||||
NAME
|
||||
----
|
||||
git-http-push - Push missing objects using HTTP/DAV.
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-http-push' [--complete] [--force] [--verbose] <url> <ref> [<ref>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Sends missing objects to remote repository, and updates the
|
||||
remote branch.
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
--complete::
|
||||
Do not assume that the remote repository is complete in its
|
||||
current state, and verify all objects in the entire local
|
||||
ref's history exist in the remote repository.
|
||||
|
||||
--force::
|
||||
Usually, the command refuses to update a remote ref that
|
||||
is not an ancestor of the local ref used to overwrite it.
|
||||
This flag disables the check. What this means is that
|
||||
the remote repository can lose commits; use it with
|
||||
care.
|
||||
|
||||
--verbose::
|
||||
Report the list of objects being walked locally and the
|
||||
list of objects successfully sent to the remote repository.
|
||||
|
||||
<ref>...:
|
||||
The remote refs to update.
|
||||
|
||||
|
||||
Specifying the Refs
|
||||
-------------------
|
||||
|
||||
A '<ref>' specification can be either a single pattern, or a pair
|
||||
of such patterns separated by a colon ":" (this means that a ref name
|
||||
cannot have a colon in it). A single pattern '<name>' is just a
|
||||
shorthand for '<name>:<name>'.
|
||||
|
||||
Each pattern pair consists of the source side (before the colon)
|
||||
and the destination side (after the colon). The ref to be
|
||||
pushed is determined by finding a match that matches the source
|
||||
side, and where it is pushed is determined by using the
|
||||
destination side.
|
||||
|
||||
- It is an error if <src> does not match exactly one of the
|
||||
local refs.
|
||||
|
||||
- If <dst> does not match any remote ref, either
|
||||
|
||||
* it has to start with "refs/"; <dst> is used as the
|
||||
destination literally in this case.
|
||||
|
||||
* <src> == <dst> and the ref that matched the <src> must not
|
||||
exist in the set of remote refs; the ref matched <src>
|
||||
locally is used as the name of the destination.
|
||||
|
||||
Without '--force', the <src> ref is stored at the remote only if
|
||||
<dst> does not exist, or <dst> is a proper subset (i.e. an
|
||||
ancestor) of <src>. This check, known as "fast forward check",
|
||||
is performed in order to avoid accidentally overwriting the
|
||||
remote ref and lose other peoples' commits from there.
|
||||
|
||||
With '--force', the fast forward check is disabled for all refs.
|
||||
|
||||
Optionally, a <ref> parameter can be prefixed with a plus '+' sign
|
||||
to disable the fast-forward check only on that ref.
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Nick Hengeveld <nickh@reactrix.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by Nick Hengeveld
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the gitlink:git[7] suite
|
@ -20,7 +20,7 @@ This manual page describes only the most frequently used options.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
--pretty=<format>:
|
||||
--pretty=<format>::
|
||||
Controls the way the commit log is formatted.
|
||||
|
||||
--max-count=<n>::
|
||||
|
78
Documentation/git-lost-found.txt
Normal file
78
Documentation/git-lost-found.txt
Normal file
@ -0,0 +1,78 @@
|
||||
git-lost-found(1)
|
||||
=================
|
||||
|
||||
NAME
|
||||
----
|
||||
git-lost-found - Recover lost refs that luckily have not yet been pruned.
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-lost-found'
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Finds dangling commits and tags from the object database, and
|
||||
creates refs to them in .git/lost-found/ directory. Commits and
|
||||
tags that dereference to commits go to .git/lost-found/commit
|
||||
and others are stored in .git/lost-found/other directory.
|
||||
|
||||
|
||||
OUTPUT
|
||||
------
|
||||
One line description from the commit and tag found along with
|
||||
their object name are printed on the standard output.
|
||||
|
||||
|
||||
EXAMPLE
|
||||
-------
|
||||
|
||||
Suppose you run 'git tag -f' and mistyped the tag to overwrite.
|
||||
The ref to your tag is overwritten, but until you run 'git
|
||||
prune', it is still there.
|
||||
|
||||
------------
|
||||
$ git lost-found
|
||||
[1ef2b196d909eed523d4f3c9bf54b78cdd6843c6] GIT 0.99.9c
|
||||
...
|
||||
------------
|
||||
|
||||
Also you can use gitk to browse how they relate to each other
|
||||
and existing (probably old) tags.
|
||||
|
||||
------------
|
||||
$ gitk $(cd .git/lost-found/commit && echo ??*)
|
||||
------------
|
||||
|
||||
After making sure that it is the object you are looking for, you
|
||||
can reconnect it to your regular .git/refs hierarchy.
|
||||
|
||||
------------
|
||||
$ git cat-file -t 1ef2b196
|
||||
tag
|
||||
$ git cat-file tag 1ef2b196
|
||||
object fa41bbce8e38c67a218415de6cfa510c7e50032a
|
||||
type commit
|
||||
tag v0.99.9c
|
||||
tagger Junio C Hamano <junkio@cox.net> 1131059594 -0800
|
||||
|
||||
GIT 0.99.9c
|
||||
|
||||
This contains the following changes from the "master" branch, since
|
||||
...
|
||||
$ git update-ref refs/tags/not-lost-anymore 1ef2b196
|
||||
$ git rev-parse not-lost-anymore
|
||||
1ef2b196d909eed523d4f3c9bf54b78cdd6843c6
|
||||
------------
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano 濱野 純 <junkio@cox.net>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
||||
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the gitlink:git[7] suite
|
@ -3,7 +3,7 @@ git-ls-files(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-ls-files - Information about files in the cache/working directory
|
||||
git-ls-files - Information about files in the index/working directory
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
|
@ -12,7 +12,7 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
This looks up the <file>(s) in the cache and, if there are any merge
|
||||
This looks up the <file>(s) in the index and, if there are any merge
|
||||
entries, passes the SHA1 hash for those files as arguments 1, 2, 3 (empty
|
||||
argument if no file), and <file> as argument 4. File modes for the three
|
||||
files are passed as arguments 5, 6 and 7.
|
||||
@ -23,7 +23,7 @@ OPTIONS
|
||||
Interpret all following arguments as filenames.
|
||||
|
||||
-a::
|
||||
Run merge against all files in the cache that need merging.
|
||||
Run merge against all files in the index that need merging.
|
||||
|
||||
-o::
|
||||
Instead of stopping at the first failed merge, do all of them
|
||||
|
@ -19,7 +19,7 @@ which drives multiple merge strategy scripts.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
include::merge-pull-opts.txt[]
|
||||
include::merge-options.txt[]
|
||||
|
||||
<msg>::
|
||||
The commit message to be used for the merge commit (in case
|
||||
@ -34,6 +34,8 @@ include::merge-pull-opts.txt[]
|
||||
least one <remote>. Specifying more than one <remote>
|
||||
obviously means you are trying an Octopus.
|
||||
|
||||
include::merge-strategies.txt[]
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
58
Documentation/git-pack-redundant.txt
Normal file
58
Documentation/git-pack-redundant.txt
Normal file
@ -0,0 +1,58 @@
|
||||
git-pack-redundant(1)
|
||||
=====================
|
||||
|
||||
NAME
|
||||
----
|
||||
git-pack-redundant - Program used to find redundant pack files.
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-pack-redundant [ --verbose ] [ --alt-odb ] < --all | .pack filename ... >'
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
This program computes which packs in your repository
|
||||
are redundant. The output is suitable for piping to
|
||||
'xargs rm' if you are in the root of the repository.
|
||||
|
||||
git-pack-redundant accepts a list of objects on standard input. Any objects
|
||||
given will be ignored when checking which packs are required. This makes the
|
||||
following command useful when wanting to remove packs which contain unreachable
|
||||
objects.
|
||||
|
||||
git-fsck-objects --full --unreachable | cut -d ' ' -f3 | \
|
||||
git-pack-redundant --all | xargs rm
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
|
||||
--all::
|
||||
Processes all packs. Any filenames on the commandline are ignored.
|
||||
|
||||
--alt-odb::
|
||||
Don't require objects present in packs from alternate object
|
||||
directories to be present in local packs.
|
||||
|
||||
--verbose::
|
||||
Outputs some statistics to stderr. Has a small performance penalty.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Lukas Sandström <lukass@etek.chalmers.se>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by Lukas Sandström <lukass@etek.chalmers.se>
|
||||
|
||||
See-Also
|
||||
--------
|
||||
gitlink:git-pack-objects[1]
|
||||
gitlink:git-repack[1]
|
||||
gitlink:git-prune-packed[1]
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the gitlink:git[7] suite
|
||||
|
@ -23,6 +23,12 @@ compression applied, stored in a single file, with an associated index file.
|
||||
|
||||
Packs are used to reduce the load on mirror systems, backup engines, disk storage, etc.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-n::
|
||||
Don't actually remove any objects, only show those that would have been
|
||||
removed.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>
|
||||
|
@ -20,53 +20,16 @@ Note that you can use `.` (current directory) as the
|
||||
<repository> to pull from the local repository -- this is useful
|
||||
when merging local branches into the current branch.
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
include::merge-options.txt[]
|
||||
|
||||
include::fetch-options.txt[]
|
||||
|
||||
include::pull-fetch-param.txt[]
|
||||
|
||||
-a, \--append::
|
||||
Append ref names and object names of fetched refs to the
|
||||
existing contents of `$GIT_DIR/FETCH_HEAD`. Without this
|
||||
option old data in `$GIT_DIR/FETCH_HEAD` will be overwritten.
|
||||
|
||||
include::merge-pull-opts.txt[]
|
||||
|
||||
|
||||
MERGE STRATEGIES
|
||||
----------------
|
||||
|
||||
resolve::
|
||||
This can only resolve two heads (i.e. the current branch
|
||||
and another branch you pulled from) using 3-way merge
|
||||
algorithm. It tries to carefully detect criss-cross
|
||||
merge ambiguities and is considered generally safe and
|
||||
fast. This is the default merge strategy when pulling
|
||||
one branch.
|
||||
|
||||
recursive::
|
||||
This can only resolve two heads using 3-way merge
|
||||
algorithm. When there are more than one common
|
||||
ancestors that can be used for 3-way merge, it creates a
|
||||
merged tree of the common ancestores and uses that as
|
||||
the reference tree for the 3-way merge. This has been
|
||||
reported to result in fewer merge conflicts without
|
||||
causing mis-merges by tests done on actual merge commits
|
||||
taken from Linux 2.6 kernel development history.
|
||||
Additionally this can detect and handle merges involving
|
||||
renames.
|
||||
|
||||
octopus::
|
||||
This resolves more than two-head case, but refuses to do
|
||||
complex merge that needs manual resolution. It is
|
||||
primarily meant to be used for bundling topic branch
|
||||
heads together. This is the default merge strategy when
|
||||
pulling more than one branch.
|
||||
|
||||
ours::
|
||||
This resolves any number of heads, but the result of the
|
||||
merge is always the current branch head. It is meant to
|
||||
be used to supersede old development history of side
|
||||
branches.
|
||||
include::merge-strategies.txt[]
|
||||
|
||||
|
||||
EXAMPLES
|
||||
@ -106,7 +69,7 @@ $ git fetch origin master:origin +pu:pu maint:maint
|
||||
$ git pull . origin
|
||||
------------------------------------------------
|
||||
+
|
||||
Here, a typical `$GIT_DIR/remotes/origin` file from a
|
||||
Here, a typical `.git/remotes/origin` file from a
|
||||
`git-clone` operation is used in combination with
|
||||
command line options to `git-fetch` to first update
|
||||
multiple branches of the local repository and then
|
||||
@ -119,7 +82,7 @@ known to have already obtained and made available
|
||||
all the necessary objects.
|
||||
|
||||
|
||||
Pull of multiple branches from one repository using `$GIT_DIR/remotes` file::
|
||||
Pull of multiple branches from one repository using `.git/remotes` file::
|
||||
+
|
||||
------------------------------------------------
|
||||
$ cat .git/remotes/origin
|
||||
@ -132,7 +95,7 @@ $ git checkout master
|
||||
$ git pull origin
|
||||
------------------------------------------------
|
||||
+
|
||||
Here, a typical `$GIT_DIR/remotes/origin` file from a
|
||||
Here, a typical `.git/remotes/origin` file from a
|
||||
`git-clone` operation has been hand-modified to include
|
||||
the branch-mapping of additional remote and local
|
||||
heads directly. A single `git-pull` operation while
|
||||
|
@ -3,7 +3,7 @@ git-read-tree(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-read-tree - Reads tree information into the directory cache
|
||||
git-read-tree - Reads tree information into the index
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@ -13,11 +13,11 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Reads the tree information given by <tree-ish> into the directory cache,
|
||||
Reads the tree information given by <tree-ish> into the index,
|
||||
but does not actually *update* any of the files it "caches". (see:
|
||||
git-checkout-index)
|
||||
|
||||
Optionally, it can merge a tree into the cache, perform a
|
||||
Optionally, it can merge a tree into the index, perform a
|
||||
fast-forward (i.e. 2-way) merge, or a 3-way merge, with the -m
|
||||
flag. When used with -m, the -u flag causes it to also update
|
||||
the files in the work tree with the result of the merge.
|
||||
@ -30,6 +30,10 @@ OPTIONS
|
||||
-m::
|
||||
Perform a merge, not just a read.
|
||||
|
||||
--reset::
|
||||
|
||||
Same as -m except that unmerged entries will be silently ignored.
|
||||
|
||||
-u::
|
||||
After a successful merge, update the files in the work
|
||||
tree with the result of the merge.
|
||||
@ -59,10 +63,10 @@ provided.
|
||||
Single Tree Merge
|
||||
~~~~~~~~~~~~~~~~~
|
||||
If only 1 tree is specified, git-read-tree operates as if the user did not
|
||||
specify '-m', except that if the original cache has an entry for a
|
||||
specify '-m', except that if the original index has an entry for a
|
||||
given pathname, and the contents of the path matches with the tree
|
||||
being read, the stat info from the cache is used. (In other words, the
|
||||
cache's stat()s take precedence over the merged tree's).
|
||||
being read, the stat info from the index is used. (In other words, the
|
||||
index's stat()s take precedence over the merged tree's).
|
||||
|
||||
That means that if you do a "git-read-tree -m <newtree>" followed by a
|
||||
"git-checkout-index -f -u -a", the "git-checkout-index" only checks out
|
||||
@ -96,7 +100,7 @@ Here are the "carry forward" rules:
|
||||
-------------------------------------------------------
|
||||
0 nothing nothing nothing (does not happen)
|
||||
1 nothing nothing exists use M
|
||||
2 nothing exists nothing remove path from cache
|
||||
2 nothing exists nothing remove path from index
|
||||
3 nothing exists exists use M
|
||||
|
||||
clean I==H I==M
|
||||
@ -109,7 +113,7 @@ Here are the "carry forward" rules:
|
||||
8 yes N/A no nothing exists fail
|
||||
9 no N/A no nothing exists fail
|
||||
|
||||
10 yes yes N/A exists nothing remove path from cache
|
||||
10 yes yes N/A exists nothing remove path from index
|
||||
11 no yes N/A exists nothing fail
|
||||
12 yes no N/A exists nothing fail
|
||||
13 no no N/A exists nothing fail
|
||||
@ -128,7 +132,7 @@ Here are the "carry forward" rules:
|
||||
20 yes yes no exists exists use M
|
||||
21 no yes no exists exists fail
|
||||
|
||||
In all "keep index" cases, the cache entry stays as in the
|
||||
In all "keep index" cases, the index entry stays as in the
|
||||
original index file. If the entry were not up to date,
|
||||
git-read-tree keeps the copy in the work tree intact when
|
||||
operating under the -u flag.
|
||||
@ -233,7 +237,7 @@ This is done to prevent you from losing your work-in-progress
|
||||
changes. To illustrate, suppose you start from what has been
|
||||
commited last to your repository:
|
||||
|
||||
$ JC=`cat .git/HEAD`
|
||||
$ JC=`git-rev-parse --verify "HEAD^0"`
|
||||
$ git-checkout-index -f -u -a $JC
|
||||
|
||||
You do random edits, without running git-update-index. And then
|
||||
@ -245,7 +249,7 @@ since you pulled from him:
|
||||
|
||||
Your work tree is still based on your HEAD ($JC), but you have
|
||||
some edits since. Three-way merge makes sure that you have not
|
||||
added or modified cache entries since $JC, and if you haven't,
|
||||
added or modified index entries since $JC, and if you haven't,
|
||||
then does the right thing. So with the following sequence:
|
||||
|
||||
$ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT
|
||||
|
@ -1,32 +0,0 @@
|
||||
git-rename(1)
|
||||
=============
|
||||
|
||||
NAME
|
||||
----
|
||||
git-rename - Script used to rename a file, directory or symlink.
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-rename' <source> <destination>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
This script is used to rename a file, directory or symlink.
|
||||
|
||||
The index is updated after successful completion, but the change must still be
|
||||
committed.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>
|
||||
Rewritten by Ryan Anderson <ryan@michonline.com>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the gitlink:git[7] suite
|
||||
|
170
Documentation/git-repo-config.txt
Normal file
170
Documentation/git-repo-config.txt
Normal file
@ -0,0 +1,170 @@
|
||||
git-repo-config(1)
|
||||
==================
|
||||
|
||||
NAME
|
||||
----
|
||||
git-repo-config - Get and set options in .git/config.
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-repo-config' name [value [value_regex]]
|
||||
'git-repo-config' --replace-all name [value [value_regex]]
|
||||
'git-repo-config' --get name [value_regex]
|
||||
'git-repo-config' --get-all name [value_regex]
|
||||
'git-repo-config' --unset name [value_regex]
|
||||
'git-repo-config' --unset-all name [value_regex]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
You can query/set/replace/unset options with this command. The name is
|
||||
actually the section and the key separated by a dot, and the value will be
|
||||
escaped.
|
||||
|
||||
If you want to set/unset an option which can occor on multiple lines, you
|
||||
should provide a POSIX regex for the value. If you want to handle the lines
|
||||
*not* matching the regex, just prepend a single exlamation mark in front
|
||||
(see EXAMPLES).
|
||||
|
||||
This command will fail if
|
||||
|
||||
. .git/config is invalid,
|
||||
. .git/config can not be written to,
|
||||
. no section was provided,
|
||||
. the section or key is invalid,
|
||||
. you try to unset an option which does not exist, or
|
||||
. you try to unset/set an option for which multiple lines match.
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
--replace-all::
|
||||
Default behaviour is to replace at most one line. This replaces
|
||||
all lines matching the key (and optionally the value_regex)
|
||||
|
||||
--get::
|
||||
Get the value for a given key (optionally filtered by a regex
|
||||
matching the value).
|
||||
|
||||
--get-all::
|
||||
Like get, but does not fail if the number of values for the key
|
||||
is not exactly one.
|
||||
|
||||
--unset::
|
||||
Remove the line matching the key from .git/config.
|
||||
|
||||
--unset-all::
|
||||
Remove all matching lines from .git/config.
|
||||
|
||||
|
||||
EXAMPLE
|
||||
-------
|
||||
|
||||
Given a .git/config like this:
|
||||
|
||||
#
|
||||
# This is the config file, and
|
||||
# a '#' or ';' character indicates
|
||||
# a comment
|
||||
#
|
||||
|
||||
; core variables
|
||||
[core]
|
||||
; Don't trust file modes
|
||||
filemode = false
|
||||
|
||||
; Our diff algorithm
|
||||
[diff]
|
||||
external = "/usr/local/bin/gnu-diff -u"
|
||||
renames = true
|
||||
|
||||
; Proxy settings
|
||||
[proxy]
|
||||
command="ssh" for "ssh://kernel.org/"
|
||||
command="proxy-command" for kernel.org
|
||||
command="myprotocol-command" for "my://"
|
||||
command=default-proxy ; for all the rest
|
||||
|
||||
you can set the filemode to true with
|
||||
|
||||
------------
|
||||
% git repo-config core.filemode true
|
||||
------------
|
||||
|
||||
The hypothetic proxy command entries actually have a postfix to discern
|
||||
to what URL they apply. Here is how to change the entry for kernel.org
|
||||
to "ssh".
|
||||
|
||||
------------
|
||||
% git repo-config proxy.command '"ssh" for kernel.org' 'for kernel.org$'
|
||||
------------
|
||||
|
||||
This makes sure that only the key/value pair for kernel.org is replaced.
|
||||
|
||||
To delete the entry for renames, do
|
||||
|
||||
------------
|
||||
% git repo-config --unset diff.renames
|
||||
------------
|
||||
|
||||
If you want to delete an entry for a multivar (like proxy.command above),
|
||||
you have to provide a regex matching the value of exactly one line.
|
||||
|
||||
To query the value for a given key, do
|
||||
|
||||
------------
|
||||
% git repo-config --get core.filemode
|
||||
------------
|
||||
|
||||
or
|
||||
|
||||
------------
|
||||
% git repo-config core.filemode
|
||||
------------
|
||||
|
||||
or, to query a multivar:
|
||||
|
||||
------------
|
||||
% git repo-config --get proxy.command "for kernel.org$"
|
||||
------------
|
||||
|
||||
If you want to know all the values for a multivar, do:
|
||||
|
||||
------------
|
||||
% git repo-config --get-all proxy.command
|
||||
------------
|
||||
|
||||
If you like to live dangerous, you can replace *all* proxy.commands by a
|
||||
new one with
|
||||
|
||||
------------
|
||||
% git repo-config --replace-all proxy.command ssh
|
||||
------------
|
||||
|
||||
However, if you really only want to replace the line for the default proxy,
|
||||
i.e. the one without a "for ..." postfix, do something like this:
|
||||
|
||||
------------
|
||||
% git repo-config proxy.command ssh '! for '
|
||||
------------
|
||||
|
||||
To actually match only values with an exclamation mark, you have to
|
||||
|
||||
------------
|
||||
% git repo-config section.key value '[!]'
|
||||
------------
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Johannes Schindelin <Johannes.Schindelin@gmx.de>
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by Johannes Schindelin.
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the gitlink:git[7] suite
|
||||
|
@ -14,19 +14,30 @@ DESCRIPTION
|
||||
Sets the current head to the specified commit and optionally resets the
|
||||
index and working tree to match.
|
||||
|
||||
This command is useful if you notice some small error in a recent
|
||||
commit (or set of commits) and want to redo that part without showing
|
||||
the undo in the history.
|
||||
|
||||
If you want to undo a commit other than the latest on a branch,
|
||||
gitlink:git-revert[1] is your friend.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
--mixed::
|
||||
Like --soft but reports what has not been updated. This is the
|
||||
default action.
|
||||
Resets the index but not the working tree (ie, the changed files
|
||||
are preserved but not marked for commit) and reports what has not
|
||||
been updated. This is the default action.
|
||||
|
||||
--soft::
|
||||
Does not touch the index file nor the working tree at all, but
|
||||
requires them in a good order.
|
||||
requires them to be in a good order. This leaves all your changed
|
||||
files "Updated but not checked in", as gitlink:git-status[1] would
|
||||
put it.
|
||||
|
||||
--hard::
|
||||
Matches the working tree and index to that of the tree being
|
||||
switched to.
|
||||
switched to. Any changes to tracked files in the working tree
|
||||
since <commit-ish> are lost.
|
||||
|
||||
<commit-ish>::
|
||||
Commit to make the current HEAD.
|
||||
|
@ -44,7 +44,7 @@ When importing incementally, you might need to edit the .git/svn2git file.
|
||||
|
||||
-i::
|
||||
Import-only: don't perform a checkout after importing. This option
|
||||
ensures the working directory and cache remain untouched and will
|
||||
ensures the working directory and index remain untouched and will
|
||||
not create them if they do not exist.
|
||||
|
||||
-t <trunk_subdir>::
|
||||
|
@ -24,8 +24,8 @@ Traditionally, `.git/HEAD` is a symlink pointing at
|
||||
we did `ln -sf refs/heads/newbranch .git/HEAD`, and when we want
|
||||
to find out which branch we are on, we did `readlink .git/HEAD`.
|
||||
This was fine, and internally that is what still happens by
|
||||
default, but on platforms that does not have working symlinks,
|
||||
or that does not have the `readlink(1)` command, this was a bit
|
||||
default, but on platforms that do not have working symlinks,
|
||||
or that do not have the `readlink(1)` command, this was a bit
|
||||
cumbersome. On some platforms, `ln -sf` does not even work as
|
||||
advertised (horrors).
|
||||
|
||||
|
@ -8,7 +8,7 @@ git-tag - Create a tag object signed with GPG
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-tag' [-a | -s | -u <key-id>] [-f] [-m <msg>] <name> [<head>]
|
||||
'git-tag' [-a | -s | -u <key-id>] [-f | -d] [-m <msg>] <name> [<head>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -30,6 +30,8 @@ A GnuPG signed tag object will be created when `-s` or `-u
|
||||
committer identity for the current user is used to find the
|
||||
GnuPG key for signing.
|
||||
|
||||
`-d <tag>` deletes the tag.
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
|
@ -8,7 +8,7 @@ git-unpack-objects - Unpack objects from a packed archive.
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-unpack-objects' [-q] <pack-file
|
||||
'git-unpack-objects' [-n] [-q] <pack-file
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
@ -19,6 +19,10 @@ one-object" format in $GIT_OBJECT_DIRECTORY.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-n::
|
||||
Only list the objects that would be unpacked, don't actually unpack
|
||||
them.
|
||||
|
||||
-q::
|
||||
The command usually shows percentage progress. This
|
||||
flag suppresses it.
|
||||
|
@ -21,7 +21,7 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Modifies the index or directory cache. Each file mentioned is updated
|
||||
into the cache and any 'unmerged' or 'needs updating' state is
|
||||
into the index and any 'unmerged' or 'needs updating' state is
|
||||
cleared.
|
||||
|
||||
The way "git-update-index" handles files it is told about can be modified
|
||||
@ -30,26 +30,26 @@ using the various options:
|
||||
OPTIONS
|
||||
-------
|
||||
--add::
|
||||
If a specified file isn't in the cache already then it's
|
||||
If a specified file isn't in the index already then it's
|
||||
added.
|
||||
Default behaviour is to ignore new files.
|
||||
|
||||
--remove::
|
||||
If a specified file is in the cache but is missing then it's
|
||||
If a specified file is in the index but is missing then it's
|
||||
removed.
|
||||
Default behaviour is to ignore removed file.
|
||||
|
||||
--refresh::
|
||||
Looks at the current cache and checks to see if merges or
|
||||
Looks at the current index and checks to see if merges or
|
||||
updates are needed by checking stat() information.
|
||||
|
||||
-q::
|
||||
Quiet. If --refresh finds that the cache needs an update, the
|
||||
Quiet. If --refresh finds that the index needs an update, the
|
||||
default behavior is to error out. This option makes
|
||||
git-update-index continue anyway.
|
||||
|
||||
--unmerged::
|
||||
If --refresh finds unmerged changes in the cache, the default
|
||||
If --refresh finds unmerged changes in the index, the default
|
||||
behavior is to error out. This option makes git-update-index
|
||||
continue anyway.
|
||||
|
||||
@ -57,10 +57,10 @@ OPTIONS
|
||||
Ignores missing files during a --refresh
|
||||
|
||||
--cacheinfo <mode> <object> <path>::
|
||||
Directly insert the specified info into the cache.
|
||||
Directly insert the specified info into the index.
|
||||
|
||||
--index-info::
|
||||
Read index info from stdin.
|
||||
Read index information from stdin.
|
||||
|
||||
--chmod=(+|-)x::
|
||||
Set the execute permissions on the updated files.
|
||||
@ -68,7 +68,7 @@ OPTIONS
|
||||
--info-only::
|
||||
Do not create objects in the object database for all
|
||||
<file> arguments that follow this flag; just insert
|
||||
their object IDs into the cache.
|
||||
their object IDs into the index.
|
||||
|
||||
--force-remove::
|
||||
Remove the file from the index even when the working directory
|
||||
@ -106,14 +106,14 @@ OPTIONS
|
||||
|
||||
Using --refresh
|
||||
---------------
|
||||
'--refresh' does not calculate a new sha1 file or bring the cache
|
||||
'--refresh' does not calculate a new sha1 file or bring the index
|
||||
up-to-date for mode/content changes. But what it *does* do is to
|
||||
"re-match" the stat information of a file with the cache, so that you
|
||||
can refresh the cache for a file that hasn't been changed but where
|
||||
"re-match" the stat information of a file with the index, so that you
|
||||
can refresh the index for a file that hasn't been changed but where
|
||||
the stat entry is out of date.
|
||||
|
||||
For example, you'd want to do this after doing a "git-read-tree", to link
|
||||
up the stat cache details with the proper files.
|
||||
up the stat index details with the proper files.
|
||||
|
||||
Using --cacheinfo or --info-only
|
||||
--------------------------------
|
||||
|
@ -3,7 +3,7 @@ git-write-tree(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-write-tree - Creates a tree object from the current cache
|
||||
git-write-tree - Creates a tree object from the current index
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
@ -12,11 +12,11 @@ SYNOPSIS
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Creates a tree object using the current cache.
|
||||
Creates a tree object using the current index.
|
||||
|
||||
The cache must be merged.
|
||||
The index must be merged.
|
||||
|
||||
Conceptually, "git-write-tree" sync()s the current directory cache contents
|
||||
Conceptually, "git-write-tree" sync()s the current index contents
|
||||
into a set of tree files.
|
||||
In order to have that match what is actually in your directory right
|
||||
now, you need to have done a "git-update-index" phase before you did the
|
||||
|
@ -8,13 +8,33 @@ git - the stupid content tracker
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-<command>' <args>
|
||||
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ARGS]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
'git' is both a program and a directory content tracker system.
|
||||
The program 'git' is just a wrapper to reach the core git programs
|
||||
(or a potty if you like, as it's not exactly porcelain but still
|
||||
brings your stuff to the plumbing).
|
||||
|
||||
This is reference information for the core git commands.
|
||||
OPTIONS
|
||||
-------
|
||||
--version::
|
||||
prints the git suite version that the 'git' program came from.
|
||||
|
||||
--help::
|
||||
prints the synopsis and a list of available commands.
|
||||
If a git command is named this option will bring up the
|
||||
man-page for that command.
|
||||
|
||||
--exec-path::
|
||||
path to wherever your core git programs are installed.
|
||||
This can also be controlled by setting the GIT_EXEC_PATH
|
||||
environment variable. If no path is given 'git' will print
|
||||
the current setting and then exit.
|
||||
|
||||
CORE GIT COMMANDS
|
||||
-----------------
|
||||
Before reading this cover to cover, you may want to take a look
|
||||
at the link:tutorial.html[tutorial] document.
|
||||
|
||||
@ -40,7 +60,7 @@ reflect recent changes.
|
||||
Commands Overview
|
||||
-----------------
|
||||
The git commands can helpfully be split into those that manipulate
|
||||
the repository, the cache and the working fileset, those that
|
||||
the repository, the index and the working fileset, those that
|
||||
interrogate and compare them, and those that moves objects and
|
||||
references between repositories.
|
||||
|
||||
@ -59,7 +79,7 @@ gitlink:git-apply[1]::
|
||||
applies it to the working tree.
|
||||
|
||||
gitlink:git-checkout-index[1]::
|
||||
Copy files from the cache to the working directory
|
||||
Copy files from the index to the working directory
|
||||
|
||||
gitlink:git-commit-tree[1]::
|
||||
Creates a new commit object
|
||||
@ -67,7 +87,7 @@ gitlink:git-commit-tree[1]::
|
||||
gitlink:git-hash-object[1]::
|
||||
Computes the object ID from a file.
|
||||
|
||||
gitlink:git-index-pack.html[1]::
|
||||
gitlink:git-index-pack[1]::
|
||||
Build pack index file for an existing packed archive.
|
||||
|
||||
gitlink:git-init-db[1]::
|
||||
@ -86,7 +106,10 @@ gitlink:git-prune-packed[1]::
|
||||
Remove extra objects that are already in pack files.
|
||||
|
||||
gitlink:git-read-tree[1]::
|
||||
Reads tree information into the directory cache
|
||||
Reads tree information into the directory index
|
||||
|
||||
gitlink:git-repo-config[1]::
|
||||
Get and set options in .git/config.
|
||||
|
||||
gitlink:git-unpack-objects[1]::
|
||||
Unpacks objects out of a packed archive.
|
||||
@ -95,7 +118,7 @@ gitlink:git-update-index[1]::
|
||||
Modifies the index or directory cache
|
||||
|
||||
gitlink:git-write-tree[1]::
|
||||
Creates a tree from the current cache
|
||||
Creates a tree from the current index
|
||||
|
||||
|
||||
Interrogation commands
|
||||
@ -105,10 +128,10 @@ gitlink:git-cat-file[1]::
|
||||
Provide content or type information for repository objects
|
||||
|
||||
gitlink:git-diff-index[1]::
|
||||
Compares content and mode of blobs between the cache and repository
|
||||
Compares content and mode of blobs between the index and repository
|
||||
|
||||
gitlink:git-diff-files[1]::
|
||||
Compares files in the working tree and the cache
|
||||
Compares files in the working tree and the index
|
||||
|
||||
gitlink:git-diff-stages[1]::
|
||||
Compares two "merge stages" in the index file.
|
||||
@ -120,7 +143,7 @@ gitlink:git-fsck-objects[1]::
|
||||
Verifies the connectivity and validity of the objects in the database
|
||||
|
||||
gitlink:git-ls-files[1]::
|
||||
Information about files in the cache/working directory
|
||||
Information about files in the index/working directory
|
||||
|
||||
gitlink:git-ls-tree[1]::
|
||||
Displays a tree object in human readable form
|
||||
@ -262,9 +285,6 @@ gitlink:git-push[1]::
|
||||
gitlink:git-rebase[1]::
|
||||
Rebase local commits to new upstream head.
|
||||
|
||||
gitlink:git-rename[1]::
|
||||
Rename files and directories.
|
||||
|
||||
gitlink:git-repack[1]::
|
||||
Pack unpacked objects in a repository.
|
||||
|
||||
@ -309,6 +329,9 @@ gitlink:git-convert-objects[1]::
|
||||
gitlink:git-cvsimport[1]::
|
||||
Salvage your data out of another SCM people love to hate.
|
||||
|
||||
gitlink:git-lost-found[1]::
|
||||
Recover lost refs that luckily have not yet been pruned.
|
||||
|
||||
gitlink:git-merge-one-file[1]::
|
||||
The standard helper program to use with "git-merge-index"
|
||||
|
||||
@ -490,8 +513,8 @@ git so take care if using Cogito etc
|
||||
|
||||
'GIT_INDEX_FILE'::
|
||||
This environment allows the specification of an alternate
|
||||
cache/index file. If not specified, the default of
|
||||
`$GIT_DIR/index` is used.
|
||||
index file. If not specified, the default of `$GIT_DIR/index`
|
||||
is used.
|
||||
|
||||
'GIT_OBJECT_DIRECTORY'::
|
||||
If the object storage directory is specified via this
|
||||
@ -533,9 +556,12 @@ Discussion[[Discussion]]
|
||||
------------------------
|
||||
include::../README[]
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and the git-list <git@vger.kernel.org>.
|
||||
Authors
|
||||
-------
|
||||
git's founding father is Linus Torvalds <torvalds@osdl.org>.
|
||||
The current git nurse is Junio C. Hamano <junkio@cox.net>.
|
||||
The git potty was written by Andres Ericsson <ae@op5.se>.
|
||||
General upbringing is handled by the git-list <git@vger.kernel.org>.
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
|
@ -43,14 +43,14 @@ DAG::
|
||||
|
||||
index::
|
||||
A collection of files with stat information, whose contents are
|
||||
stored as objects. The cache is a stored version of your working
|
||||
stored as objects. The index is a stored version of your working
|
||||
tree. Truth be told, it can also contain a second, and even a third
|
||||
version of a working tree, which are used when merging.
|
||||
|
||||
index entry::
|
||||
The information regarding a particular file, stored in the index.
|
||||
An index entry can be unmerged, if a merge was started, but not
|
||||
yet finished (i.e. if the cache contains multiple versions of
|
||||
yet finished (i.e. if the index contains multiple versions of
|
||||
that file).
|
||||
|
||||
unmerged index:
|
||||
@ -75,7 +75,7 @@ checkout::
|
||||
stored in the object database.
|
||||
|
||||
commit::
|
||||
As a verb: The action of storing the current state of the cache in the
|
||||
As a verb: The action of storing the current state of the index in the
|
||||
object database. The result is a revision.
|
||||
As a noun: Short hand for commit object.
|
||||
|
||||
|
65
Documentation/howto/isolate-bugs-with-bisect.txt
Normal file
65
Documentation/howto/isolate-bugs-with-bisect.txt
Normal file
@ -0,0 +1,65 @@
|
||||
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 laste)
|
||||
|
||||
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 bew "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.
|
||||
|
@ -63,7 +63,7 @@ And then, you can just remove the broken branch if you decide you really
|
||||
don't want it:
|
||||
|
||||
# remove 'broken' branch
|
||||
rm .git/refs/heads/broken
|
||||
git branch -d broken
|
||||
|
||||
# Prune old objects if you're really really sure
|
||||
git prune
|
||||
|
@ -40,10 +40,7 @@ So I started from master, made a bunch of edits, and committed:
|
||||
$ git checkout master
|
||||
$ cd Documentation; ed git.txt ...
|
||||
$ cd ..; git add Documentation/*.txt
|
||||
$ git commit -s -v
|
||||
|
||||
NOTE. The -v flag to commit is a handy way to make sure that
|
||||
your additions are not introducing bogusly formatted lines.
|
||||
$ git commit -s
|
||||
|
||||
After the commit, the ancestry graph would look like this:
|
||||
|
||||
@ -98,7 +95,7 @@ to do cherrypicking using only the core GIT tools.
|
||||
Let's go back to the earlier picture, with different labels.
|
||||
|
||||
You, as an individual developer, cloned upstream repository and
|
||||
amde a couple of commits on top of it.
|
||||
made a couple of commits on top of it.
|
||||
|
||||
*your "master" head
|
||||
upstream --> #1 --> #2 --> #3
|
||||
|
@ -153,7 +153,8 @@ Everything is in the good order. I do not need the temporary branch
|
||||
nor tag anymore, so remove them:
|
||||
|
||||
------------------------------------------------
|
||||
$ rm -f .git/refs/tags/pu-anchor .git/refs/heads/revert-c99
|
||||
$ rm -f .git/refs/tags/pu-anchor
|
||||
$ git branch -d revert-c99
|
||||
------------------------------------------------
|
||||
|
||||
It was an emergency fix, so we might as well merge it into the
|
||||
|
105
Documentation/howto/update-hook-example.txt
Normal file
105
Documentation/howto/update-hook-example.txt
Normal file
@ -0,0 +1,105 @@
|
||||
From: Junio C Hamano <junkio@cox.net>
|
||||
Subject: control access to branches.
|
||||
Date: Thu, 17 Nov 2005 23:55:32 -0800
|
||||
Message-ID: <7vfypumlu3.fsf@assigned-by-dhcp.cox.net>
|
||||
Abstract: An example hooks/update script is presented to
|
||||
implement repository maintenance policies, such as who can push
|
||||
into which branch and who can make a tag.
|
||||
|
||||
When your developer runs git-push into the repository,
|
||||
git-receive-pack is run (either locally or over ssh) as that
|
||||
developer, so is hooks/update script. Quoting from the relevant
|
||||
section of the documentation:
|
||||
|
||||
Before each ref is updated, if $GIT_DIR/hooks/update file exists
|
||||
and executable, it is called with three parameters:
|
||||
|
||||
$GIT_DIR/hooks/update refname sha1-old sha1-new
|
||||
|
||||
The refname parameter is relative to $GIT_DIR; e.g. for the
|
||||
master head this is "refs/heads/master". Two sha1 are the
|
||||
object names for the refname before and after the update. Note
|
||||
that the hook is called before the refname is updated, so either
|
||||
sha1-old is 0{40} (meaning there is no such ref yet), or it
|
||||
should match what is recorded in refname.
|
||||
|
||||
So if your policy is (1) always require fast-forward push
|
||||
(i.e. never allow "git-push repo +branch:branch"), (2) you
|
||||
have a list of users allowed to update each branch, and (3) you
|
||||
do not let tags to be overwritten, then:
|
||||
|
||||
#!/bin/sh
|
||||
# This is a sample hooks/update script, written by JC
|
||||
# in his e-mail buffer, so naturally it is not tested
|
||||
# but hopefully would convey the idea.
|
||||
|
||||
umask 002
|
||||
case "$1" in
|
||||
refs/tags/*)
|
||||
# No overwriting an existing tag
|
||||
if test -f "$GIT_DIR/$1"
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/heads/*)
|
||||
# No rebasing or rewinding
|
||||
if expr "$2" : '0*$' >/dev/null
|
||||
then
|
||||
# creating a new branch
|
||||
;
|
||||
else
|
||||
# updating -- make sure it is a fast forward
|
||||
mb=`git-merge-base "$2" "$3"`
|
||||
case "$mb,$2" in
|
||||
"$2,$mb")
|
||||
;; # fast forward -- happy
|
||||
*)
|
||||
exit 1 ;; # unhappy
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# No funny refs allowed
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Is the user allowed to update it?
|
||||
me=`id -u -n` ;# e.g. "junio"
|
||||
while read head_pattern users
|
||||
do
|
||||
if expr "$1" : "$head_pattern" >/dev/null
|
||||
then
|
||||
case " $users " in
|
||||
*" $me "*)
|
||||
exit 0 ;; # happy
|
||||
' * ')
|
||||
exit 0 ;; # anybody
|
||||
esac
|
||||
fi
|
||||
done
|
||||
exit 1
|
||||
|
||||
For the sake of simplicity, I assumed that you keep something
|
||||
like this in $GIT_DIR/info/allowed-pushers file:
|
||||
|
||||
refs/heads/master junio
|
||||
refs/heads/cogito$ pasky
|
||||
refs/heads/bw/ linus
|
||||
refs/heads/tmp/ *
|
||||
refs/tags/v[0-9]* junio
|
||||
|
||||
With this, Linus can push or create "bw/penguin" or "bw/zebra"
|
||||
or "bw/panda" branches, Pasky can do only "cogito", and I can do
|
||||
master branch and make versioned tags. And anybody can do
|
||||
tmp/blah branches. This assumes all the users are in a single
|
||||
group that can write into $GIT_DIR/ and underneath.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@ GIT as a Linux subsystem maintainer.
|
||||
|
||||
-Tony
|
||||
|
||||
Last updated w.r.t. GIT 0.99.5
|
||||
Last updated w.r.t. GIT 0.99.9f
|
||||
|
||||
Linux subsystem maintenance using GIT
|
||||
-------------------------------------
|
||||
@ -89,8 +89,8 @@ out at the current tip of the linus branch.
|
||||
|
||||
These can be easily kept up to date by merging from the "linus" branch:
|
||||
|
||||
$ git checkout test && git resolve test linus "Auto-update from upstream"
|
||||
$ git checkout release && git resolve release linus "Auto-update from upstream"
|
||||
$ git checkout test && git merge "Auto-update from upstream" test linus
|
||||
$ git checkout release && git merge "Auto-update from upstream" release linus
|
||||
|
||||
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
|
||||
@ -128,7 +128,7 @@ commit to this branch.
|
||||
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 resolve test speed-up-spinlocks "Pull speed-up-spinlock changes"
|
||||
$ 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.
|
||||
@ -138,7 +138,7 @@ 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 resolve release speed-up-spinlocks "Pull speed-up-spinlock changes"
|
||||
$ 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
|
||||
@ -166,7 +166,7 @@ output from:
|
||||
|
||||
is empty. At this point the branch can be deleted:
|
||||
|
||||
$ rm .git/refs/heads/branchname
|
||||
$ 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
|
||||
@ -190,7 +190,7 @@ Here are some of the scripts that I use to simplify all this even further.
|
||||
|
||||
case "$1" in
|
||||
test|release)
|
||||
git checkout $1 && git resolve $1 linus "Auto-update from upstream"
|
||||
git checkout $1 && git merge "Auto-update from upstream" $1 linus
|
||||
;;
|
||||
linus)
|
||||
before=$(cat .git/refs/heads/linus)
|
||||
@ -231,7 +231,7 @@ test|release)
|
||||
echo $1 already merged into $2 1>&2
|
||||
exit 1
|
||||
fi
|
||||
git checkout $2 && git resolve $2 $1 "Pull $1 into $2 branch"
|
||||
git checkout $2 && git merge "Pull $1 into $2 branch" $2 $1
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
T="$1"
|
||||
|
||||
for h in *.html howto/*.txt howto/*.html
|
||||
for h in *.html *.txt howto/*.txt howto/*.html
|
||||
do
|
||||
diff -u -I'Last updated [0-9][0-9]-[A-Z][a-z][a-z]-' "$T/$h" "$h" || {
|
||||
echo >&2 "# install $h $T/$h"
|
||||
@ -12,7 +12,7 @@ do
|
||||
}
|
||||
done
|
||||
strip_leading=`echo "$T/" | sed -e 's|.|.|g'`
|
||||
for th in "$T"/*.html "$T"/howto/*.txt "$T"/howto/*.html
|
||||
for th in "$T"/*.html "$T"/*.txt "$T"/howto/*.txt "$T"/howto/*.html
|
||||
do
|
||||
h=`expr "$th" : "$strip_leading"'\(.*\)'`
|
||||
case "$h" in
|
||||
|
16
Documentation/merge-options.txt
Normal file
16
Documentation/merge-options.txt
Normal file
@ -0,0 +1,16 @@
|
||||
-n, \--no-summary::
|
||||
Do not show diffstat at the end of the merge.
|
||||
|
||||
--no-commit::
|
||||
Perform the merge but pretend the merge failed and do
|
||||
not autocommit, to give the user a chance to inspect and
|
||||
further tweak the merge result before committing.
|
||||
|
||||
|
||||
-s <strategy>, \--strategy=<strategy>::
|
||||
Use the given merge strategy; can be supplied more than
|
||||
once to specify them in the order they should be tried.
|
||||
If there is no `-s` option, a built-in list of strategies
|
||||
is used instead (`git-merge-resolve` when merging a single
|
||||
head, `git-merge-octopus` otherwise).
|
||||
|
@ -1,14 +0,0 @@
|
||||
-n, --no-summary::
|
||||
Do not show diffstat at the end of the merge.
|
||||
|
||||
--no-commit::
|
||||
Perform the merge but pretend the merge failed and do
|
||||
not autocommit, to give the user a chance to inspect and
|
||||
further tweak the merge result before committing.
|
||||
|
||||
-s <strategy>::
|
||||
use that merge strategy; can be given more than once to
|
||||
specify them in the order they should be tried. If
|
||||
there is no `-s` option, built-in list of strategies is
|
||||
used instead (`git-merge-resolve` when merging a single
|
||||
head, `git-merge-octopus` otherwise).
|
35
Documentation/merge-strategies.txt
Normal file
35
Documentation/merge-strategies.txt
Normal file
@ -0,0 +1,35 @@
|
||||
MERGE STRATEGIES
|
||||
----------------
|
||||
|
||||
resolve::
|
||||
This can only resolve two heads (i.e. the current branch
|
||||
and another branch you pulled from) using 3-way merge
|
||||
algorithm. It tries to carefully detect criss-cross
|
||||
merge ambiguities and is considered generally safe and
|
||||
fast. This is the default merge strategy when pulling
|
||||
one branch.
|
||||
|
||||
recursive::
|
||||
This can only resolve two heads using 3-way merge
|
||||
algorithm. When there are more than one common
|
||||
ancestors that can be used for 3-way merge, it creates a
|
||||
merged tree of the common ancestores and uses that as
|
||||
the reference tree for the 3-way merge. This has been
|
||||
reported to result in fewer merge conflicts without
|
||||
causing mis-merges by tests done on actual merge commits
|
||||
taken from Linux 2.6 kernel development history.
|
||||
Additionally this can detect and handle merges involving
|
||||
renames.
|
||||
|
||||
octopus::
|
||||
This resolves more than two-head case, but refuses to do
|
||||
complex merge that needs manual resolution. It is
|
||||
primarily meant to be used for bundling topic branch
|
||||
heads together. This is the default merge strategy when
|
||||
pulling more than one branch.
|
||||
|
||||
ours::
|
||||
This resolves any number of heads, but the result of the
|
||||
merge is always the current branch head. It is meant to
|
||||
be used to supersede old development history of side
|
||||
branches.
|
@ -5,11 +5,31 @@
|
||||
to name the remote repository:
|
||||
+
|
||||
===============================================================
|
||||
- Rsync URL: rsync://remote.machine/path/to/repo.git/
|
||||
- HTTP(s) URL: http://remote.machine/path/to/repo.git/
|
||||
- git URL: git://remote.machine/path/to/repo.git/
|
||||
or remote.machine:/path/to/repo.git/
|
||||
- Local directory: /path/to/repo.git/
|
||||
- rsync://host.xz/path/to/repo.git/
|
||||
- http://host.xz/path/to/repo.git/
|
||||
- https://host.xz/path/to/repo.git/
|
||||
- git://host.xz/path/to/repo.git/
|
||||
- git://host.xz/~user/path/to/repo.git/
|
||||
- ssh://host.xz/path/to/repo.git/
|
||||
- ssh://host.xz/~user/path/to/repo.git/
|
||||
- ssh://host.xz/~/path/to/repo.git
|
||||
===============================================================
|
||||
+
|
||||
SSH Is the default transport protocol and also supports an
|
||||
scp-like syntax. Both syntaxes support username expansion,
|
||||
as does the native git protocol. The following three are
|
||||
identical to the last three above, respectively:
|
||||
+
|
||||
===============================================================
|
||||
- host.xz:/path/to/repo.git/
|
||||
- host.xz:~user/path/to/repo.git/
|
||||
- host.xz:path/to/repo.git
|
||||
===============================================================
|
||||
+
|
||||
To sync with a local directory, use:
|
||||
|
||||
===============================================================
|
||||
- /path/to/repo.git/
|
||||
===============================================================
|
||||
+
|
||||
In addition to the above, as a short-hand, the name of a
|
||||
@ -82,14 +102,19 @@ must know this is the expected usage pattern for a branch.
|
||||
[NOTE]
|
||||
You never do your own development on branches that appear
|
||||
on the right hand side of a <refspec> colon on `Pull:` lines;
|
||||
they are to be updated by `git-fetch`. The corollary is that
|
||||
a local branch should be introduced and named on a <refspec>
|
||||
right-hand-side if you intend to do development derived from
|
||||
that branch.
|
||||
This leads to the common `Pull: master:origin` mapping of a
|
||||
remote `master` branch to a local `origin` branch, which
|
||||
is then merged to a local development branch, again typically
|
||||
named `master`.
|
||||
they are to be updated by `git-fetch`. If you intend to do
|
||||
development derived from a remote branch `B`, have a `Pull:`
|
||||
line to track it (i.e. `Pull: B:remote-B`), and have a separate
|
||||
branch `my-B` to do your development on top of it. The latter
|
||||
is created by `git branch my-B remote-B` (or its equivalent `git
|
||||
checkout -b my-B remote-B`). Run `git fetch` to keep track of
|
||||
the progress of the remote side, and when you see something new
|
||||
on the remote branch, merge it into your development branch with
|
||||
`git pull . remote-B`, while you are on `my-B` branch.
|
||||
The common `Pull: master:origin` mapping of a remote `master`
|
||||
branch to a local `origin` branch, which is then merged to a
|
||||
ocal development branch, again typically named `master`, is made
|
||||
when you run `git clone` for you to follow this pattern.
|
||||
+
|
||||
[NOTE]
|
||||
There is a difference between listing multiple <refspec>
|
||||
|
@ -36,14 +36,16 @@ To start up, create a subdirectory for it, change into that
|
||||
subdirectory, and initialize the git infrastructure with `git-init-db`:
|
||||
|
||||
------------------------------------------------
|
||||
mkdir git-tutorial
|
||||
cd git-tutorial
|
||||
git-init-db
|
||||
$ mkdir git-tutorial
|
||||
$ cd git-tutorial
|
||||
$ git-init-db
|
||||
------------------------------------------------
|
||||
|
||||
to which git will reply
|
||||
|
||||
defaulting to local storage area
|
||||
----------------
|
||||
defaulting to local storage area
|
||||
----------------
|
||||
|
||||
which is just git's way of saying that you haven't been doing anything
|
||||
strange, and that it will have created a local `.git` directory setup for
|
||||
@ -114,8 +116,8 @@ in your git repository. We'll start off with a few bad examples, just to
|
||||
get a feel for how this works:
|
||||
|
||||
------------------------------------------------
|
||||
echo "Hello World" >hello
|
||||
echo "Silly example" >example
|
||||
$ echo "Hello World" >hello
|
||||
$ echo "Silly example" >example
|
||||
------------------------------------------------
|
||||
|
||||
you have now created two files in your working tree (aka 'working directory'), but to
|
||||
@ -129,7 +131,7 @@ actually check in your hard work, you will have to go through two steps:
|
||||
The first step is trivial: when you want to tell git about any changes
|
||||
to your working tree, you use the `git-update-index` program. That
|
||||
program normally just takes a list of filenames you want to update, but
|
||||
to avoid trivial mistakes, it refuses to add new entries to the cache
|
||||
to avoid trivial mistakes, it refuses to add new entries to the index
|
||||
(or remove existing ones) unless you explicitly tell it that you're
|
||||
adding a new entry with the `\--add` flag (or removing an entry with the
|
||||
`\--remove`) flag.
|
||||
@ -137,7 +139,7 @@ adding a new entry with the `\--add` flag (or removing an entry with the
|
||||
So to populate the index with the two files you just created, you can do
|
||||
|
||||
------------------------------------------------
|
||||
git-update-index --add hello example
|
||||
$ git-update-index --add hello example
|
||||
------------------------------------------------
|
||||
|
||||
and you have now told git to track those two files.
|
||||
@ -146,12 +148,17 @@ In fact, as you did that, if you now look into your object directory,
|
||||
you'll notice that git will have added two new objects to the object
|
||||
database. If you did exactly the steps above, you should now be able to do
|
||||
|
||||
ls .git/objects/??/*
|
||||
|
||||
----------------
|
||||
$ ls .git/objects/??/*
|
||||
----------------
|
||||
|
||||
and see two files:
|
||||
|
||||
.git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238
|
||||
.git/objects/f2/4c74a2e500f5ee1332c86b94199f52b1d1d962
|
||||
----------------
|
||||
.git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238
|
||||
.git/objects/f2/4c74a2e500f5ee1332c86b94199f52b1d1d962
|
||||
----------------
|
||||
|
||||
which correspond with the objects with names of 557db... and f24c7..
|
||||
respectively.
|
||||
@ -159,13 +166,17 @@ respectively.
|
||||
If you want to, you can use `git-cat-file` to look at those objects, but
|
||||
you'll have to use the object name, not the filename of the object:
|
||||
|
||||
git-cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238
|
||||
----------------
|
||||
$ git-cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238
|
||||
----------------
|
||||
|
||||
where the `-t` tells `git-cat-file` to tell you what the "type" of the
|
||||
object is. git will tell you that you have a "blob" object (ie just a
|
||||
regular file), and you can see the contents with
|
||||
|
||||
git-cat-file "blob" 557db03
|
||||
----------------
|
||||
$ git-cat-file "blob" 557db03
|
||||
----------------
|
||||
|
||||
which will print out "Hello World". The object 557db03 is nothing
|
||||
more than the contents of your file `hello`.
|
||||
@ -188,7 +199,7 @@ was just to show that `git-update-index` did something magical, and
|
||||
actually saved away the contents of your files into the git object
|
||||
database.
|
||||
|
||||
Updating the cache did something else too: it created a `.git/index`
|
||||
Updating the index did something else too: it created a `.git/index`
|
||||
file. This is the index that describes your current working tree, and
|
||||
something you should be very aware of. Again, you normally never worry
|
||||
about the index file itself, but you should be aware of the fact that
|
||||
@ -202,7 +213,7 @@ In particular, let's not even check in the two files into git yet, we'll
|
||||
start off by adding another line to `hello` first:
|
||||
|
||||
------------------------------------------------
|
||||
echo "It's a new day for git" >>hello
|
||||
$ echo "It's a new day for git" >>hello
|
||||
------------------------------------------------
|
||||
|
||||
and you can now, since you told git about the previous state of `hello`, ask
|
||||
@ -210,7 +221,7 @@ git what has changed in the tree compared to your old index, using the
|
||||
`git-diff-files` command:
|
||||
|
||||
------------
|
||||
git-diff-files
|
||||
$ git-diff-files
|
||||
------------
|
||||
|
||||
Oops. That wasn't very readable. It just spit out its own internal
|
||||
@ -222,12 +233,7 @@ To make it readable, we can tell git-diff-files to output the
|
||||
differences as a patch, using the `-p` flag:
|
||||
|
||||
------------
|
||||
git-diff-files -p
|
||||
------------
|
||||
|
||||
which will spit out
|
||||
|
||||
------------
|
||||
$ git-diff-files -p
|
||||
diff --git a/hello b/hello
|
||||
index 557db03..263414f 100644
|
||||
--- a/hello
|
||||
@ -264,13 +270,15 @@ filenames with their contents (and their permissions), and we're
|
||||
creating the equivalent of a git "directory" object:
|
||||
|
||||
------------------------------------------------
|
||||
git-write-tree
|
||||
$ git-write-tree
|
||||
------------------------------------------------
|
||||
|
||||
and this will just output the name of the resulting tree, in this case
|
||||
(if you have done exactly as I've described) it should be
|
||||
|
||||
8988da15d077d4829fc51d8544c097def6644dbb
|
||||
----------------
|
||||
8988da15d077d4829fc51d8544c097def6644dbb
|
||||
----------------
|
||||
|
||||
which is another incomprehensible object name. Again, if you want to,
|
||||
you can use `git-cat-file -t 8988d\...` to see that this time the object
|
||||
@ -299,14 +307,16 @@ that's exactly what `git-commit-tree` spits out, we can do this
|
||||
all with a sequence of simple shell commands:
|
||||
|
||||
------------------------------------------------
|
||||
tree=$(git-write-tree)
|
||||
commit=$(echo 'Initial commit' | git-commit-tree $tree)
|
||||
git-update-ref HEAD $(commit)
|
||||
$ tree=$(git-write-tree)
|
||||
$ commit=$(echo 'Initial commit' | git-commit-tree $tree)
|
||||
$ git-update-ref HEAD $commit
|
||||
------------------------------------------------
|
||||
|
||||
which will say:
|
||||
|
||||
Committing initial tree 8988da15d077d4829fc51d8544c097def6644dbb
|
||||
----------------
|
||||
Committing initial tree 8988da15d077d4829fc51d8544c097def6644dbb
|
||||
----------------
|
||||
|
||||
just to warn you about the fact that it created a totally new commit
|
||||
that is not related to anything else. Normally you do this only *once*
|
||||
@ -349,7 +359,9 @@ didn't have anything to diff against.
|
||||
|
||||
But now we can do
|
||||
|
||||
git-diff-index -p HEAD
|
||||
----------------
|
||||
$ git-diff-index -p HEAD
|
||||
----------------
|
||||
|
||||
(where `-p` has the same meaning as it did in `git-diff-files`), and it
|
||||
will show us the same difference, but for a totally different reason.
|
||||
@ -360,7 +372,9 @@ are obviously the same, so we get the same result.
|
||||
Again, because this is a common operation, you can also just shorthand
|
||||
it with
|
||||
|
||||
git diff HEAD
|
||||
----------------
|
||||
$ git diff HEAD
|
||||
----------------
|
||||
|
||||
which ends up doing the above for you.
|
||||
|
||||
@ -396,7 +410,7 @@ work through the index file, so the first thing we need to do is to
|
||||
update the index cache:
|
||||
|
||||
------------------------------------------------
|
||||
git-update-index hello
|
||||
$ git-update-index hello
|
||||
------------------------------------------------
|
||||
|
||||
(note how we didn't need the `\--add` flag this time, since git knew
|
||||
@ -417,7 +431,7 @@ this wasn't an initial commit any more), but you've done that once
|
||||
already, so let's just use the helpful script this time:
|
||||
|
||||
------------------------------------------------
|
||||
git commit
|
||||
$ git commit
|
||||
------------------------------------------------
|
||||
|
||||
which starts an editor for you to write the commit message and tells you
|
||||
@ -426,7 +440,7 @@ a bit about what you have done.
|
||||
Write whatever message you want, and all the lines that start with '#'
|
||||
will be pruned out, and the rest will be used as the commit message for
|
||||
the change. If you decide you don't want to commit anything after all at
|
||||
this point (you can continue to edit things and update the cache), you
|
||||
this point (you can continue to edit things and update the index), you
|
||||
can just leave an empty message. Otherwise `git commit` will commit
|
||||
the change for you.
|
||||
|
||||
@ -450,7 +464,9 @@ give it just a single commit object, and it will figure out the parent
|
||||
of that commit itself, and show the difference directly. Thus, to get
|
||||
the same diff that we've already seen several times, we can now do
|
||||
|
||||
git-diff-tree -p HEAD
|
||||
----------------
|
||||
$ git-diff-tree -p HEAD
|
||||
----------------
|
||||
|
||||
(again, `-p` means to show the difference as a human-readable patch),
|
||||
and it will show what the last commit (in `HEAD`) actually changed.
|
||||
@ -505,13 +521,17 @@ activities.
|
||||
To see the whole history of our pitiful little git-tutorial project, you
|
||||
can do
|
||||
|
||||
git log
|
||||
----------------
|
||||
$ git log
|
||||
----------------
|
||||
|
||||
which shows just the log messages, or if we want to see the log together
|
||||
with the associated patches use the more complex (and much more
|
||||
powerful)
|
||||
|
||||
git-whatchanged -p --root
|
||||
----------------
|
||||
$ git-whatchanged -p --root
|
||||
----------------
|
||||
|
||||
and you will see exactly what has changed in the repository over its
|
||||
short history.
|
||||
@ -547,14 +567,16 @@ it in the `.git/refs/tags/` subdirectory instead of calling it a `head`.
|
||||
So the simplest form of tag involves nothing more than
|
||||
|
||||
------------------------------------------------
|
||||
git tag my-first-tag
|
||||
$ git tag my-first-tag
|
||||
------------------------------------------------
|
||||
|
||||
which just writes the current `HEAD` into the `.git/refs/tags/my-first-tag`
|
||||
file, after which point you can then use this symbolic name for that
|
||||
particular state. You can, for example, do
|
||||
|
||||
git diff my-first-tag
|
||||
----------------
|
||||
$ git diff my-first-tag
|
||||
----------------
|
||||
|
||||
to diff your current state against that tag (which at this point will
|
||||
obviously be an empty diff, but if you continue to develop and commit
|
||||
@ -568,7 +590,9 @@ you really did
|
||||
that tag. You create these annotated tags with either the `-a` or
|
||||
`-s` flag to `git tag`:
|
||||
|
||||
git tag -s <tagname>
|
||||
----------------
|
||||
$ git tag -s <tagname>
|
||||
----------------
|
||||
|
||||
which will sign the current `HEAD` (but you can also give it another
|
||||
argument that specifies the thing to tag, ie you could have tagged the
|
||||
@ -584,8 +608,8 @@ name for the state at that point.
|
||||
Copying repositories
|
||||
--------------------
|
||||
|
||||
git repositories are normally totally self-sufficient, and it's worth noting
|
||||
that unlike CVS, for example, there is no separate notion of
|
||||
git repositories are normally totally self-sufficient and relocatable
|
||||
Unlike CVS, for example, there is no separate notion of
|
||||
"repository" and "working tree". A git repository normally *is* the
|
||||
working tree, with the local git information hidden in the `.git`
|
||||
subdirectory. There is nothing else. What you see is what you got.
|
||||
@ -602,8 +626,10 @@ This has two implications:
|
||||
|
||||
- if you grow bored with the tutorial repository you created (or you've
|
||||
made a mistake and want to start all over), you can just do simple
|
||||
|
||||
rm -rf git-tutorial
|
||||
+
|
||||
----------------
|
||||
$ rm -rf git-tutorial
|
||||
----------------
|
||||
+
|
||||
and it will be gone. There's no external repository, and there's no
|
||||
history outside the project you created.
|
||||
@ -618,8 +644,10 @@ Note that when you've moved or copied a git repository, your git index
|
||||
file (which caches various information, notably some of the "stat"
|
||||
information for the files involved) will likely need to be refreshed.
|
||||
So after you do a `cp -a` to create a new copy, you'll want to do
|
||||
|
||||
git-update-index --refresh
|
||||
+
|
||||
----------------
|
||||
$ git-update-index --refresh
|
||||
----------------
|
||||
+
|
||||
in the new repository to make sure that the index file is up-to-date.
|
||||
|
||||
@ -633,8 +661,10 @@ repositories you often want to make sure that the index cache is in some
|
||||
known state (you don't know *what* they've done and not yet checked in),
|
||||
so usually you'll precede the `git-update-index` with a
|
||||
|
||||
git-read-tree --reset HEAD
|
||||
git-update-index --refresh
|
||||
----------------
|
||||
$ git-read-tree --reset HEAD
|
||||
$ git-update-index --refresh
|
||||
----------------
|
||||
|
||||
which will force a total index re-build from the tree pointed to by `HEAD`.
|
||||
It resets the index contents to `HEAD`, and then the `git-update-index`
|
||||
@ -645,7 +675,9 @@ tells you they need to be updated.
|
||||
|
||||
The above can also be written as simply
|
||||
|
||||
git reset
|
||||
----------------
|
||||
$ git reset
|
||||
----------------
|
||||
|
||||
and in fact a lot of the common git command combinations can be scripted
|
||||
with the `git xyz` interfaces. You can learn things by just looking
|
||||
@ -665,20 +697,26 @@ first create your own subdirectory for the project, and then copy the
|
||||
raw repository contents into the `.git` directory. For example, to
|
||||
create your own copy of the git repository, you'd do the following
|
||||
|
||||
mkdir my-git
|
||||
cd my-git
|
||||
rsync -rL rsync://rsync.kernel.org/pub/scm/git/git.git/ .git
|
||||
----------------
|
||||
$ mkdir my-git
|
||||
$ cd my-git
|
||||
$ rsync -rL rsync://rsync.kernel.org/pub/scm/git/git.git/ .git
|
||||
----------------
|
||||
|
||||
followed by
|
||||
|
||||
git-read-tree HEAD
|
||||
----------------
|
||||
$ git-read-tree HEAD
|
||||
----------------
|
||||
|
||||
to populate the index. However, now you have populated the index, and
|
||||
you have all the git internal files, but you will notice that you don't
|
||||
actually have any of the working tree files to work on. To get
|
||||
those, you'd check them out with
|
||||
|
||||
git-checkout-index -u -a
|
||||
----------------
|
||||
$ git-checkout-index -u -a
|
||||
----------------
|
||||
|
||||
where the `-u` flag means that you want the checkout to keep the index
|
||||
up-to-date (so that you don't have to refresh it afterward), and the
|
||||
@ -689,9 +727,11 @@ files).
|
||||
|
||||
Again, this can all be simplified with
|
||||
|
||||
git clone rsync://rsync.kernel.org/pub/scm/git/git.git/ my-git
|
||||
cd my-git
|
||||
git checkout
|
||||
----------------
|
||||
$ git clone rsync://rsync.kernel.org/pub/scm/git/git.git/ my-git
|
||||
$ cd my-git
|
||||
$ git checkout
|
||||
----------------
|
||||
|
||||
which will end up doing all of the above for you.
|
||||
|
||||
@ -719,7 +759,7 @@ used earlier, and create a branch in it. You do that by simply just
|
||||
saying that you want to check out a new branch:
|
||||
|
||||
------------
|
||||
git checkout -b mybranch
|
||||
$ git checkout -b mybranch
|
||||
------------
|
||||
|
||||
will create a new branch based at the current `HEAD` position, and switch
|
||||
@ -733,7 +773,7 @@ just telling `git checkout` what the base of the checkout would be.
|
||||
In other words, if you have an earlier tag or branch, you'd just do
|
||||
|
||||
------------
|
||||
git checkout -b mybranch earlier-commit
|
||||
$ git checkout -b mybranch earlier-commit
|
||||
------------
|
||||
|
||||
and it would create the new branch `mybranch` at the earlier commit,
|
||||
@ -743,27 +783,27 @@ and check out the state at that time.
|
||||
You can always just jump back to your original `master` branch by doing
|
||||
|
||||
------------
|
||||
git checkout master
|
||||
$ git checkout master
|
||||
------------
|
||||
|
||||
(or any other branch-name, for that matter) and if you forget which
|
||||
branch you happen to be on, a simple
|
||||
|
||||
------------
|
||||
ls -l .git/HEAD
|
||||
$ ls -l .git/HEAD
|
||||
------------
|
||||
|
||||
will tell you where it's pointing (Note that on platforms with bad or no
|
||||
symlink support, you have to execute
|
||||
|
||||
------------
|
||||
cat .git/HEAD
|
||||
$ cat .git/HEAD
|
||||
------------
|
||||
|
||||
instead). To get the list of branches you have, you can say
|
||||
|
||||
------------
|
||||
git branch
|
||||
$ git branch
|
||||
------------
|
||||
|
||||
which is nothing more than a simple script around `ls .git/refs/heads`.
|
||||
@ -773,7 +813,7 @@ Sometimes you may wish to create a new branch _without_ actually
|
||||
checking it out and switching to it. If so, just use the command
|
||||
|
||||
------------
|
||||
git branch <branchname> [startingpoint]
|
||||
$ git branch <branchname> [startingpoint]
|
||||
------------
|
||||
|
||||
which will simply _create_ the branch, but will not do anything further.
|
||||
@ -792,9 +832,9 @@ being the same as the original `master` branch, let's make sure we're in
|
||||
that branch, and do some work there.
|
||||
|
||||
------------------------------------------------
|
||||
git checkout mybranch
|
||||
echo "Work, work, work" >>hello
|
||||
git commit -m 'Some work.' hello
|
||||
$ git checkout mybranch
|
||||
$ echo "Work, work, work" >>hello
|
||||
$ git commit -m 'Some work.' hello
|
||||
------------------------------------------------
|
||||
|
||||
Here, we just added another line to `hello`, and we used a shorthand for
|
||||
@ -807,7 +847,7 @@ does some work in the original branch, and simulate that by going back
|
||||
to the master branch, and editing the same file differently there:
|
||||
|
||||
------------
|
||||
git checkout master
|
||||
$ git checkout master
|
||||
------------
|
||||
|
||||
Here, take a moment to look at the contents of `hello`, and notice how they
|
||||
@ -815,9 +855,9 @@ don't contain the work we just did in `mybranch` -- because that work
|
||||
hasn't happened in the `master` branch at all. Then do
|
||||
|
||||
------------
|
||||
echo "Play, play, play" >>hello
|
||||
echo "Lots of fun" >>example
|
||||
git commit -m 'Some fun.' hello example
|
||||
$ echo "Play, play, play" >>hello
|
||||
$ echo "Lots of fun" >>example
|
||||
$ git commit -m 'Some fun.' hello example
|
||||
------------
|
||||
|
||||
since the master branch is obviously in a much better mood.
|
||||
@ -826,7 +866,9 @@ Now, you've got two branches, and you decide that you want to merge the
|
||||
work done. Before we do that, let's introduce a cool graphical tool that
|
||||
helps you view what's going on:
|
||||
|
||||
gitk --all
|
||||
----------------
|
||||
$ gitk --all
|
||||
----------------
|
||||
|
||||
will show you graphically both of your branches (that's what the `\--all`
|
||||
means: normally it will just show you your current `HEAD`) and their
|
||||
@ -836,14 +878,14 @@ source.
|
||||
Anyway, let's exit `gitk` (`^Q` or the File menu), and decide that we want
|
||||
to merge the work we did on the `mybranch` branch into the `master`
|
||||
branch (which is currently our `HEAD` too). To do that, there's a nice
|
||||
script called `git resolve`, which wants to know which branches you want
|
||||
script called `git merge`, which wants to know which branches you want
|
||||
to resolve and what the merge is all about:
|
||||
|
||||
------------
|
||||
git resolve HEAD mybranch "Merge work in mybranch"
|
||||
$ git merge "Merge work in mybranch" HEAD mybranch
|
||||
------------
|
||||
|
||||
where the third argument is going to be used as the commit message if
|
||||
where the first argument is going to be used as the commit message if
|
||||
the merge can be resolved automatically.
|
||||
|
||||
Now, in this case we've intentionally created a situation where the
|
||||
@ -851,12 +893,16 @@ merge will need to be fixed up by hand, though, so git will do as much
|
||||
of it as it can automatically (which in this case is just merge the `example`
|
||||
file, which had no differences in the `mybranch` branch), and say:
|
||||
|
||||
Simple merge failed, trying Automatic merge
|
||||
Auto-merging hello.
|
||||
----------------
|
||||
Trying really trivial in-index merge...
|
||||
fatal: Merge requires file-level merging
|
||||
Nope.
|
||||
...
|
||||
merge: warning: conflicts during merge
|
||||
ERROR: Merge conflict in hello.
|
||||
fatal: merge program failed
|
||||
Automatic merge failed, fix up by hand
|
||||
Automatic merge failed/prevented; fix up by hand
|
||||
----------------
|
||||
|
||||
which is way too verbose, but it basically tells you that it failed the
|
||||
really trivial merge ("Simple merge") and did an "Automatic merge"
|
||||
@ -877,7 +923,7 @@ Work, work, work
|
||||
and once you're happy with your manual merge, just do a
|
||||
|
||||
------------
|
||||
git commit hello
|
||||
$ git commit hello
|
||||
------------
|
||||
|
||||
which will very loudly warn you that you're now committing a merge
|
||||
@ -927,17 +973,19 @@ to the `master` branch. Let's go back to `mybranch`, and run
|
||||
resolve to get the "upstream changes" back to your branch.
|
||||
|
||||
------------
|
||||
git checkout mybranch
|
||||
git resolve HEAD master "Merge upstream changes."
|
||||
$ git checkout mybranch
|
||||
$ git merge "Merge upstream changes." HEAD master
|
||||
------------
|
||||
|
||||
This outputs something like this (the actual commit object names
|
||||
would be different)
|
||||
|
||||
Updating from ae3a2da... to a80b4aa....
|
||||
example | 1 +
|
||||
hello | 1 +
|
||||
2 files changed, 2 insertions(+), 0 deletions(-)
|
||||
----------------
|
||||
Updating from ae3a2da... to a80b4aa....
|
||||
example | 1 +
|
||||
hello | 1 +
|
||||
2 files changed, 2 insertions(+), 0 deletions(-)
|
||||
----------------
|
||||
|
||||
Because your branch did not contain anything more than what are
|
||||
already merged into the `master` branch, the resolve operation did
|
||||
@ -963,14 +1011,16 @@ Merging external work
|
||||
It's usually much more common that you merge with somebody else than
|
||||
merging with your own branches, so it's worth pointing out that git
|
||||
makes that very easy too, and in fact, it's not that different from
|
||||
doing a `git resolve`. In fact, a remote merge ends up being nothing
|
||||
doing a `git merge`. In fact, a remote merge ends up being nothing
|
||||
more than "fetch the work from a remote repository into a temporary tag"
|
||||
followed by a `git resolve`.
|
||||
followed by a `git merge`.
|
||||
|
||||
Fetching from a remote repository is done by, unsurprisingly,
|
||||
`git fetch`:
|
||||
|
||||
git fetch <remote-repository>
|
||||
----------------
|
||||
$ git fetch <remote-repository>
|
||||
----------------
|
||||
|
||||
One of the following transports can be used to name the
|
||||
repository to download from:
|
||||
@ -1015,7 +1065,7 @@ This transport was designed for anonymous downloading. Like SSH
|
||||
transport, it finds out the set of objects the downstream side
|
||||
lacks and transfers (close to) minimum set of objects.
|
||||
|
||||
HTTP(s)::
|
||||
HTTP(S)::
|
||||
`http://remote.machine/path/to/repo.git/`
|
||||
+
|
||||
HTTP and HTTPS transport are used only for downloading. They
|
||||
@ -1045,7 +1095,9 @@ However -- it's such a common thing to `fetch` and then
|
||||
immediately `resolve`, that it's called `git pull`, and you can
|
||||
simply do
|
||||
|
||||
git pull <remote-repository>
|
||||
----------------
|
||||
$ git pull <remote-repository>
|
||||
----------------
|
||||
|
||||
and optionally give a branch-name for the remote end as a second
|
||||
argument.
|
||||
@ -1073,8 +1125,8 @@ the remote repository URL in a file under .git/remotes/
|
||||
directory, like this:
|
||||
|
||||
------------------------------------------------
|
||||
mkdir -p .git/remotes/
|
||||
cat >.git/remotes/linus <<\EOF
|
||||
$ mkdir -p .git/remotes/
|
||||
$ cat >.git/remotes/linus <<\EOF
|
||||
URL: http://www.kernel.org/pub/scm/git/git.git/
|
||||
EOF
|
||||
------------------------------------------------
|
||||
@ -1084,7 +1136,7 @@ The URL specified in such file can even be a prefix
|
||||
of a full URL, like this:
|
||||
|
||||
------------------------------------------------
|
||||
cat >.git/remotes/jgarzik <<\EOF
|
||||
$ cat >.git/remotes/jgarzik <<\EOF
|
||||
URL: http://www.kernel.org/pub/scm/linux/git/jgarzik/
|
||||
EOF
|
||||
------------------------------------------------
|
||||
@ -1103,6 +1155,156 @@ the above are equivalent to:
|
||||
. `git pull http://www.kernel.org/pub/.../jgarzik/netdev-2.6.git e100`
|
||||
|
||||
|
||||
How does the merge work?
|
||||
------------------------
|
||||
|
||||
We said this tutorial shows what plumbing does to help you cope
|
||||
with the porcelain that isn't flushing, but we so far did not
|
||||
talk about how the merge really works. If you are following
|
||||
this tutorial the first time, I'd suggest to skip to "Publishing
|
||||
your work" section and come back here later.
|
||||
|
||||
OK, still with me? To give us an example to look at, let's go
|
||||
back to the earlier repository with "hello" and "example" file,
|
||||
and bring ourselves back to the pre-merge state:
|
||||
|
||||
------------
|
||||
$ git show-branch --more=3 master mybranch
|
||||
! [master] Merge work in mybranch
|
||||
* [mybranch] Merge work in mybranch
|
||||
--
|
||||
++ [master] Merge work in mybranch
|
||||
++ [master^2] Some work.
|
||||
++ [master^] Some fun.
|
||||
------------
|
||||
|
||||
Remember, before running `git merge`, our `master` head was at
|
||||
"Some fun." commit, while our `mybranch` head was at "Some
|
||||
work." commit.
|
||||
|
||||
------------
|
||||
$ git checkout mybranch
|
||||
$ git reset --hard master^2
|
||||
$ git checkout master
|
||||
$ git reset --hard master^
|
||||
------------
|
||||
|
||||
After rewinding, the commit structure should look like this:
|
||||
|
||||
------------
|
||||
$ git show-branch
|
||||
* [master] Some fun.
|
||||
! [mybranch] Some work.
|
||||
--
|
||||
+ [mybranch] Some work.
|
||||
+ [master] Some fun.
|
||||
++ [mybranch^] New day.
|
||||
------------
|
||||
|
||||
Now we are ready to experiment with the merge by hand.
|
||||
|
||||
`git merge` command, when merging two branches, uses 3-way merge
|
||||
algorithm. First, it finds the common ancestor between them.
|
||||
The command it uses is `git-merge-base`:
|
||||
|
||||
------------
|
||||
$ mb=$(git-merge-base HEAD mybranch)
|
||||
------------
|
||||
|
||||
The command writes the commit object name of the common ancestor
|
||||
to the standard output, so we captured its output to a variable,
|
||||
because we will be using it in the next step. BTW, the common
|
||||
ancestor commit is the "New day." commit in this case. You can
|
||||
tell it by:
|
||||
|
||||
------------
|
||||
$ git-name-rev $mb
|
||||
my-first-tag
|
||||
------------
|
||||
|
||||
After finding out a common ancestor commit, the second step is
|
||||
this:
|
||||
|
||||
------------
|
||||
$ git-read-tree -m -u $mb HEAD mybranch
|
||||
------------
|
||||
|
||||
This is the same `git-read-tree` command we have already seen,
|
||||
but it takes three trees, unlike previous examples. This reads
|
||||
the contents of each tree into different 'stage' in the index
|
||||
file (the first tree goes to stage 1, the second stage 2,
|
||||
etc.). After reading three trees into three stages, the paths
|
||||
that are the same in all three stages are 'collapsed' into stage
|
||||
0. Also paths that are the same in two of three stages are
|
||||
collapsed into stage 0, taking the SHA1 from either stage 2 or
|
||||
stage 3, whichever is different from stage 1 (i.e. only one side
|
||||
changed from the common ancestor).
|
||||
|
||||
After 'collapsing' operation, paths that are different in three
|
||||
trees are left in non-zero stages. At this point, you can
|
||||
inspect the index file with this command:
|
||||
|
||||
------------
|
||||
$ git-ls-files --stage
|
||||
100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example
|
||||
100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1 hello
|
||||
100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2 hello
|
||||
100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello
|
||||
------------
|
||||
|
||||
In our example of only two files, we did not have unchanged
|
||||
files so only 'example' resulted in collapsing, but in real-life
|
||||
large projects, only small number of files change in one commit,
|
||||
and this 'collapsing' tends to trivially merge most of the paths
|
||||
fairly quickly, leaving only a handful the real changes in non-zero
|
||||
stages.
|
||||
|
||||
To look at only non-zero stages, use `\--unmerged` flag:
|
||||
|
||||
------------
|
||||
$ git-ls-files --unmerged
|
||||
100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1 hello
|
||||
100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2 hello
|
||||
100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello
|
||||
------------
|
||||
|
||||
The next step of merging is to merge these three versions of the
|
||||
file, using 3-way merge. This is done by giving
|
||||
`git-merge-one-file` command as one of the arguments to
|
||||
`git-merge-index` command:
|
||||
|
||||
------------
|
||||
$ git-merge-index git-merge-one-file hello
|
||||
Auto-merging hello.
|
||||
merge: warning: conflicts during merge
|
||||
ERROR: Merge conflict in hello.
|
||||
fatal: merge program failed
|
||||
------------
|
||||
|
||||
`git-merge-one-file` script is called with parameters to
|
||||
describe those three versions, and is responsible to leave the
|
||||
merge results in the working tree and register it in the index
|
||||
file. It is a fairly straightforward shell script, and
|
||||
eventually calls `merge` program from RCS suite to perform the
|
||||
file-level 3-way merge. In this case, `merge` detects
|
||||
conflicts, and the merge result with conflict marks is left in
|
||||
the working tree, while the index file is updated with the
|
||||
version from the current branch (this is to make `git diff`
|
||||
useful after this step). This can be seen if you run `ls-files
|
||||
--stage` again at this point:
|
||||
|
||||
------------
|
||||
$ git-ls-files --stage
|
||||
100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example
|
||||
100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 0 hello
|
||||
------------
|
||||
|
||||
As you can see, there is no unmerged paths in the index file.
|
||||
This is the state of the index file and the working file after
|
||||
`git merge` returns control back to you, leaving the conflicting
|
||||
merge for you to resolve.
|
||||
|
||||
|
||||
Publishing your work
|
||||
--------------------
|
||||
|
||||
@ -1148,7 +1350,7 @@ project `my-git`. After logging into the remote machine, create
|
||||
an empty directory:
|
||||
|
||||
------------
|
||||
mkdir my-git.git
|
||||
$ mkdir my-git.git
|
||||
------------
|
||||
|
||||
Then, make that directory into a git repository by running
|
||||
@ -1156,7 +1358,7 @@ Then, make that directory into a git repository by running
|
||||
`.git`, we do things slightly differently:
|
||||
|
||||
------------
|
||||
GIT_DIR=my-git.git git-init-db
|
||||
$ GIT_DIR=my-git.git git-init-db
|
||||
------------
|
||||
|
||||
Make sure this directory is available for others you want your
|
||||
@ -1182,7 +1384,7 @@ Come back to the machine you have your private repository. From
|
||||
there, run this command:
|
||||
|
||||
------------
|
||||
git push <public-host>:/path/to/my-git.git master
|
||||
$ git push <public-host>:/path/to/my-git.git master
|
||||
------------
|
||||
|
||||
This synchronizes your public repository to match the named
|
||||
@ -1194,7 +1396,7 @@ repository. Kernel.org mirror network takes care of the
|
||||
propagation to other publicly visible machines:
|
||||
|
||||
------------
|
||||
git push master.kernel.org:/pub/scm/git/git.git/
|
||||
$ git push master.kernel.org:/pub/scm/git/git.git/
|
||||
------------
|
||||
|
||||
|
||||
@ -1209,7 +1411,7 @@ immutable once they are created, there is a way to optimize the
|
||||
storage by "packing them together". The command
|
||||
|
||||
------------
|
||||
git repack
|
||||
$ git repack
|
||||
------------
|
||||
|
||||
will do it for you. If you followed the tutorial examples, you
|
||||
@ -1235,7 +1437,7 @@ Once you have packed objects, you do not need to leave the
|
||||
unpacked objects that are contained in the pack file anymore.
|
||||
|
||||
------------
|
||||
git prune-packed
|
||||
$ git prune-packed
|
||||
------------
|
||||
|
||||
would remove them for you.
|
||||
@ -1332,7 +1534,10 @@ on that project and has an own "public repository" goes like this:
|
||||
the "project lead" person does.
|
||||
|
||||
3. Copy over the packed files from "project lead" public
|
||||
repository to your public repository.
|
||||
repository to your public repository, unless the "project
|
||||
lead" repository lives on the same machine as yours. In the
|
||||
latter case, you can use `objects/info/alternates` file to
|
||||
point at the repository you are borrowing from.
|
||||
|
||||
4. Push into the public repository from your primary
|
||||
repository. Run `git repack`, and possibly `git prune` if the
|
||||
@ -1464,8 +1669,8 @@ in both of them. You could merge in 'diff-fix' first and then
|
||||
'commit-fix' next, like this:
|
||||
|
||||
------------
|
||||
$ git resolve master diff-fix 'Merge fix in diff-fix'
|
||||
$ git resolve master commit-fix 'Merge fix in commit-fix'
|
||||
$ git merge 'Merge fix in diff-fix' master diff-fix
|
||||
$ git merge 'Merge fix in commit-fix' master commit-fix
|
||||
------------
|
||||
|
||||
Which would result in:
|
||||
@ -1498,8 +1703,8 @@ $ git reset --hard master~2
|
||||
------------
|
||||
|
||||
You can make sure 'git show-branch' matches the state before
|
||||
those two 'git resolve' you just did. Then, instead of running
|
||||
two 'git resolve' commands in a row, you would pull these two
|
||||
those two 'git merge' you just did. Then, instead of running
|
||||
two 'git merge' commands in a row, you would pull these two
|
||||
branch heads (this is known as 'making an Octopus'):
|
||||
|
||||
------------
|
||||
|
24
INSTALL
24
INSTALL
@ -5,10 +5,13 @@ Normally you can just do "make" followed by "make install", and that
|
||||
will install the git programs in your own ~/bin/ directory. If you want
|
||||
to do a global install, you can do
|
||||
|
||||
make prefix=/usr install
|
||||
$ make prefix=/usr ;# as yourself
|
||||
# make prefix=/usr install ;# as root
|
||||
|
||||
(or prefix=/usr/local, of course). Some day somebody may send me a RPM
|
||||
spec file or something, and you can do "make rpm" or whatever.
|
||||
(or prefix=/usr/local, of course). Just like any program suite
|
||||
that uses $prefix, the built results have some paths encoded,
|
||||
which are derived from $prefix, so "make all; make prefix=/usr
|
||||
install" would not work.
|
||||
|
||||
Issues of note:
|
||||
|
||||
@ -46,6 +49,9 @@ Issues of note:
|
||||
transfer, you are probabaly OK if you do not have
|
||||
them.
|
||||
|
||||
- expat library; git-http-push uses it for remote lock
|
||||
management over DAV. Similar to "curl" above, this is optional.
|
||||
|
||||
- "GNU diff" to generate patches. Of course, you don't _have_ to
|
||||
generate patches if you don't want to, but let's face it, you'll
|
||||
be wanting to. Or why did you get git in the first place?
|
||||
@ -69,3 +75,15 @@ Issues of note:
|
||||
history graphically
|
||||
|
||||
- "ssh" is used to push and pull over the net
|
||||
|
||||
- "perl" and POSIX-compliant shells are needed to use most of
|
||||
the barebone Porcelainish scripts.
|
||||
|
||||
- "python" 2.3 or more recent; if you have 2.3, you may need
|
||||
to build with "make WITH_OWN_SUBPROCESS_PY=YesPlease".
|
||||
|
||||
- Some platform specific issues are dealt with Makefile rules,
|
||||
but depending on your specific installation, you may not
|
||||
have all the libraries/tools needed, or you may have
|
||||
necessary libraries at unusual locations. Please look at the
|
||||
top of the Makefile to see what can be adjusted for your needs.
|
||||
|
172
Makefile
172
Makefile
@ -6,12 +6,16 @@
|
||||
# Define NO_OPENSSL environment variable if you do not have OpenSSL. You will
|
||||
# miss out git-rev-list --merge-order. This also implies MOZILLA_SHA1.
|
||||
#
|
||||
# Define NO_CURL if you do not have curl installed. git-http-pull is not
|
||||
# built, and you cannot use http:// and https:// transports.
|
||||
# Define NO_CURL if you do not have curl installed. git-http-pull and
|
||||
# git-http-push are not built, and you cannot use http:// and https://
|
||||
# transports.
|
||||
#
|
||||
# Define CURLDIR=/foo/bar if your curl header and library files are in
|
||||
# /foo/bar/include and /foo/bar/lib directories.
|
||||
#
|
||||
# Define NO_EXPAT if you do not have expat installed. git-http-push is
|
||||
# not built, and you cannot push using http:// and https:// transports.
|
||||
#
|
||||
# Define NO_STRCASESTR if you don't have strcasestr.
|
||||
#
|
||||
# Define PPC_SHA1 environment variable when running make to make use of
|
||||
@ -37,25 +41,23 @@
|
||||
# 1461501637330902918203684832716283019655932542976 hashes do not give you
|
||||
# sufficient guarantee that no collisions between objects will ever happen.
|
||||
|
||||
# DEFINES += -DCOLLISION_CHECK
|
||||
|
||||
# Define USE_NSEC below if you want git to care about sub-second file mtimes
|
||||
# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
|
||||
# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
|
||||
# randomly break unless your underlying filesystem supports those sub-second
|
||||
# times (my ext3 doesn't).
|
||||
|
||||
# DEFINES += -DUSE_NSEC
|
||||
|
||||
# Define USE_STDEV below if you want git to care about the underlying device
|
||||
# change being considered an inode change from the update-cache perspective.
|
||||
|
||||
# DEFINES += -DUSE_STDEV
|
||||
GIT_VERSION = 0.99.9k
|
||||
|
||||
GIT_VERSION = 0.99.9d
|
||||
# CFLAGS and LDFLAGS are for the users to override from the command line.
|
||||
|
||||
CFLAGS = -g -O2 -Wall
|
||||
ALL_CFLAGS = $(CFLAGS) $(PLATFORM_DEFINES) $(DEFINES)
|
||||
LDFLAGS =
|
||||
ALL_CFLAGS = $(CFLAGS)
|
||||
ALL_LDFLAGS = $(LDFLAGS)
|
||||
|
||||
prefix = $(HOME)
|
||||
bindir = $(prefix)/bin
|
||||
@ -86,23 +88,29 @@ SCRIPT_SH = \
|
||||
git-prune.sh git-pull.sh git-push.sh git-rebase.sh \
|
||||
git-repack.sh git-request-pull.sh git-reset.sh \
|
||||
git-resolve.sh git-revert.sh git-sh-setup.sh git-status.sh \
|
||||
git-tag.sh git-verify-tag.sh git-whatchanged.sh git.sh \
|
||||
git-tag.sh git-verify-tag.sh git-whatchanged.sh \
|
||||
git-applymbox.sh git-applypatch.sh git-am.sh \
|
||||
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
|
||||
git-merge-resolve.sh git-merge-ours.sh git-grep.sh
|
||||
git-merge-resolve.sh git-merge-ours.sh git-grep.sh \
|
||||
git-lost-found.sh
|
||||
|
||||
SCRIPT_PERL = \
|
||||
git-archimport.perl git-cvsimport.perl git-relink.perl \
|
||||
git-rename.perl git-shortlog.perl git-fmt-merge-msg.perl \
|
||||
git-svnimport.perl git-mv.perl
|
||||
git-shortlog.perl git-fmt-merge-msg.perl \
|
||||
git-svnimport.perl git-mv.perl git-cvsexportcommit.perl
|
||||
|
||||
SCRIPT_PYTHON = \
|
||||
git-merge-recursive.py
|
||||
|
||||
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
|
||||
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
|
||||
$(patsubst %.py,%,$(SCRIPT_PYTHON)) \
|
||||
gitk git-cherry-pick
|
||||
|
||||
# The ones that do not have to link with lcrypto nor lz.
|
||||
SIMPLE_PROGRAMS = \
|
||||
git-get-tar-commit-id$X git-mailinfo$X git-mailsplit$X \
|
||||
git-stripspace$X git-var$X git-daemon$X
|
||||
git-stripspace$X git-daemon$X
|
||||
|
||||
# ... and all the rest
|
||||
PROGRAMS = \
|
||||
@ -122,18 +130,36 @@ PROGRAMS = \
|
||||
git-unpack-objects$X git-update-index$X git-update-server-info$X \
|
||||
git-upload-pack$X git-verify-pack$X git-write-tree$X \
|
||||
git-update-ref$X git-symbolic-ref$X git-check-ref-format$X \
|
||||
git-name-rev$X $(SIMPLE_PROGRAMS)
|
||||
git-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X
|
||||
|
||||
# what 'all' will build and 'install' will install.
|
||||
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS) git$X
|
||||
|
||||
# Backward compatibility -- to be removed after 1.0
|
||||
PROGRAMS += git-ssh-pull$X git-ssh-push$X
|
||||
|
||||
GIT_LIST_TWEAK =
|
||||
|
||||
# Set paths to tools early so that they can be used for version tests.
|
||||
ifndef SHELL_PATH
|
||||
SHELL_PATH = /bin/sh
|
||||
endif
|
||||
ifndef PERL_PATH
|
||||
PERL_PATH = /usr/bin/perl
|
||||
endif
|
||||
ifndef PYTHON_PATH
|
||||
PYTHON_PATH = /usr/bin/python
|
||||
endif
|
||||
|
||||
PYMODULES = \
|
||||
gitMergeCommon.py
|
||||
|
||||
ifdef WITH_OWN_SUBPROCESS_PY
|
||||
PYMODULES += compat/subprocess.py
|
||||
else
|
||||
ifneq ($(shell $(PYTHON_PATH) -c 'import subprocess;print"OK"' 2>/dev/null),OK)
|
||||
PYMODULES += compat/subprocess.py
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef WITH_SEND_EMAIL
|
||||
@ -185,6 +211,12 @@ uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
|
||||
ifeq ($(uname_S),Darwin)
|
||||
NEEDS_SSL_WITH_CRYPTO = YesPlease
|
||||
NEEDS_LIBICONV = YesPlease
|
||||
## fink
|
||||
ALL_CFLAGS += -I/sw/include
|
||||
ALL_LDFLAGS += -L/sw/lib
|
||||
## darwinports
|
||||
ALL_CFLAGS += -I/opt/local/include
|
||||
ALL_LDFLAGS += -L/opt/local/lib
|
||||
endif
|
||||
ifeq ($(uname_S),SunOS)
|
||||
NEEDS_SOCKET = YesPlease
|
||||
@ -194,19 +226,29 @@ ifeq ($(uname_S),SunOS)
|
||||
NO_STRCASESTR = YesPlease
|
||||
INSTALL = ginstall
|
||||
TAR = gtar
|
||||
PLATFORM_DEFINES += -D__EXTENSIONS__
|
||||
ALL_CFLAGS += -D__EXTENSIONS__
|
||||
endif
|
||||
ifeq ($(uname_O),Cygwin)
|
||||
NO_STRCASESTR = YesPlease
|
||||
NEEDS_LIBICONV = YesPlease
|
||||
# There are conflicting reports about this.
|
||||
# On some boxes NO_MMAP is needed, and not so elsewhere.
|
||||
# Try uncommenting this if you see things break -- YMMV.
|
||||
# NO_MMAP = YesPlease
|
||||
NO_IPV6 = YesPlease
|
||||
X = .exe
|
||||
PLATFORM_DEFINES += -DUSE_SYMLINK_HEAD=0
|
||||
ALL_CFLAGS += -DUSE_SYMLINK_HEAD=0
|
||||
endif
|
||||
ifeq ($(uname_S),OpenBSD)
|
||||
NO_STRCASESTR = YesPlease
|
||||
NEEDS_LIBICONV = YesPlease
|
||||
PLATFORM_DEFINES += -I/usr/local/include -L/usr/local/lib
|
||||
ALL_CFLAGS += -I/usr/local/include
|
||||
ALL_LDFLAGS += -L/usr/local/lib
|
||||
endif
|
||||
ifeq ($(uname_S),NetBSD)
|
||||
NEEDS_LIBICONV = YesPlease
|
||||
ALL_CFLAGS += -I/usr/pkg/include
|
||||
ALL_LDFLAGS += -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib
|
||||
endif
|
||||
ifneq (,$(findstring arm,$(uname_M)))
|
||||
ARM_SHA1 = YesPlease
|
||||
@ -216,23 +258,20 @@ endif
|
||||
|
||||
ifndef NO_CURL
|
||||
ifdef CURLDIR
|
||||
# This is still problematic -- gcc does not want -R.
|
||||
CFLAGS += -I$(CURLDIR)/include
|
||||
# This is still problematic -- gcc does not always want -R.
|
||||
ALL_CFLAGS += -I$(CURLDIR)/include
|
||||
CURL_LIBCURL = -L$(CURLDIR)/lib -R$(CURLDIR)/lib -lcurl
|
||||
else
|
||||
CURL_LIBCURL = -lcurl
|
||||
endif
|
||||
PROGRAMS += git-http-fetch$X
|
||||
endif
|
||||
|
||||
ifndef SHELL_PATH
|
||||
SHELL_PATH = /bin/sh
|
||||
endif
|
||||
ifndef PERL_PATH
|
||||
PERL_PATH = /usr/bin/perl
|
||||
endif
|
||||
ifndef PYTHON_PATH
|
||||
PYTHON_PATH = /usr/bin/python
|
||||
curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
|
||||
ifeq "$(curl_check)" "070908"
|
||||
ifndef NO_EXPAT
|
||||
EXPAT_LIBEXPAT = -lexpat
|
||||
PROGRAMS += git-http-push$X
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef NO_OPENSSL
|
||||
@ -240,13 +279,13 @@ ifndef NO_OPENSSL
|
||||
OPENSSL_LIBSSL = -lssl
|
||||
ifdef OPENSSLDIR
|
||||
# Again this may be problematic -- gcc does not always want -R.
|
||||
CFLAGS += -I$(OPENSSLDIR)/include
|
||||
ALL_CFLAGS += -I$(OPENSSLDIR)/include
|
||||
OPENSSL_LINK = -L$(OPENSSLDIR)/lib -R$(OPENSSLDIR)/lib
|
||||
else
|
||||
OPENSSL_LINK =
|
||||
endif
|
||||
else
|
||||
DEFINES += -DNO_OPENSSL
|
||||
ALL_CFLAGS += -DNO_OPENSSL
|
||||
MOZILLA_SHA1 = 1
|
||||
OPENSSL_LIBSSL =
|
||||
endif
|
||||
@ -258,7 +297,7 @@ endif
|
||||
ifdef NEEDS_LIBICONV
|
||||
ifdef ICONVDIR
|
||||
# Again this may be problematic -- gcc does not always want -R.
|
||||
CFLAGS += -I$(ICONVDIR)/include
|
||||
ALL_CFLAGS += -I$(ICONVDIR)/include
|
||||
ICONV_LINK = -L$(ICONVDIR)/lib -R$(ICONVDIR)/lib
|
||||
else
|
||||
ICONV_LINK =
|
||||
@ -276,15 +315,15 @@ ifdef NEEDS_NSL
|
||||
SIMPLE_LIB += -lnsl
|
||||
endif
|
||||
ifdef NO_STRCASESTR
|
||||
DEFINES += -Dstrcasestr=gitstrcasestr -DNO_STRCASESTR=1
|
||||
ALL_CFLAGS += -Dstrcasestr=gitstrcasestr -DNO_STRCASESTR=1
|
||||
LIB_OBJS += compat/strcasestr.o
|
||||
endif
|
||||
ifdef NO_MMAP
|
||||
DEFINES += -Dmmap=gitfakemmap -Dmunmap=gitfakemunmap -DNO_MMAP
|
||||
ALL_CFLAGS += -Dmmap=gitfakemmap -Dmunmap=gitfakemunmap -DNO_MMAP
|
||||
LIB_OBJS += compat/mmap.o
|
||||
endif
|
||||
ifdef NO_IPV6
|
||||
DEFINES += -DNO_IPV6 -Dsockaddr_storage=sockaddr_in
|
||||
ALL_CFLAGS += -DNO_IPV6 -Dsockaddr_storage=sockaddr_in
|
||||
endif
|
||||
|
||||
ifdef PPC_SHA1
|
||||
@ -305,31 +344,22 @@ endif
|
||||
endif
|
||||
endif
|
||||
|
||||
DEFINES += -DSHA1_HEADER=$(call shellquote,$(SHA1_HEADER))
|
||||
|
||||
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
|
||||
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
|
||||
$(patsubst %.py,%,$(SCRIPT_PYTHON)) \
|
||||
gitk git-cherry-pick
|
||||
ALL_CFLAGS += -DSHA1_HEADER=$(call shellquote,$(SHA1_HEADER))
|
||||
|
||||
export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
|
||||
### Build rules
|
||||
|
||||
all: $(PROGRAMS) $(SCRIPTS)
|
||||
all: $(ALL_PROGRAMS)
|
||||
|
||||
all:
|
||||
$(MAKE) -C templates
|
||||
|
||||
git: git.sh Makefile
|
||||
rm -f $@+ $@
|
||||
sed -e '1s|#!.*/sh|#!$(call shq,$(SHELL_PATH))|' \
|
||||
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
|
||||
-e 's/@@X@@/$(X)/g' \
|
||||
$(GIT_LIST_TWEAK) <$@.sh >$@+
|
||||
chmod +x $@+
|
||||
mv $@+ $@
|
||||
# Only use $(CFLAGS). We don't need anything else.
|
||||
git$(X): git.c Makefile
|
||||
$(CC) -DGIT_EXEC_PATH='"$(bindir)"' -DGIT_VERSION='"$(GIT_VERSION)"' \
|
||||
$(CFLAGS) $< -o $@
|
||||
|
||||
$(filter-out git,$(patsubst %.sh,%,$(SCRIPT_SH))) : % : %.sh
|
||||
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
|
||||
rm -f $@
|
||||
sed -e '1s|#!.*/sh|#!$(call shq,$(SHELL_PATH))|' \
|
||||
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
|
||||
@ -360,14 +390,16 @@ git-cherry-pick: git-revert
|
||||
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
|
||||
|
||||
git-%$X: %.o $(LIB_FILE)
|
||||
$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)
|
||||
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
|
||||
|
||||
git-mailinfo$X : SIMPLE_LIB += $(LIB_4_ICONV)
|
||||
$(SIMPLE_PROGRAMS) : $(LIB_FILE)
|
||||
$(SIMPLE_PROGRAMS) : git-%$X : %.o
|
||||
$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIB_FILE) $(SIMPLE_LIB)
|
||||
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
|
||||
$(LIB_FILE) $(SIMPLE_LIB)
|
||||
|
||||
git-http-fetch$X: fetch.o
|
||||
git-http-fetch$X: fetch.o http.o
|
||||
git-http-push$X: http.o
|
||||
git-local-fetch$X: fetch.o
|
||||
git-ssh-fetch$X: rsh.o fetch.o
|
||||
git-ssh-upload$X: rsh.o
|
||||
@ -375,6 +407,7 @@ git-ssh-pull$X: rsh.o fetch.o
|
||||
git-ssh-push$X: rsh.o
|
||||
|
||||
git-http-fetch$X: LIBS += $(CURL_LIBCURL)
|
||||
git-http-push$X: LIBS += $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
|
||||
git-rev-list$X: LIBS += $(OPENSSL_LIBSSL)
|
||||
|
||||
init-db.o: init-db.c
|
||||
@ -398,10 +431,10 @@ test: all
|
||||
$(MAKE) -C t/ all
|
||||
|
||||
test-date$X: test-date.c date.o ctype.o
|
||||
$(CC) $(ALL_CFLAGS) -o $@ test-date.c date.o ctype.o
|
||||
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) test-date.c date.o ctype.o
|
||||
|
||||
test-delta$X: test-delta.c diff-delta.o patch-delta.o
|
||||
$(CC) $(ALL_CFLAGS) -o $@ $^
|
||||
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^
|
||||
|
||||
check:
|
||||
for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i; done
|
||||
@ -410,9 +443,9 @@ check:
|
||||
|
||||
### Installation rules
|
||||
|
||||
install: $(PROGRAMS) $(SCRIPTS)
|
||||
install: all
|
||||
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(bindir))
|
||||
$(INSTALL) $(PROGRAMS) $(SCRIPTS) $(call shellquote,$(DESTDIR)$(bindir))
|
||||
$(INSTALL) $(ALL_PROGRAMS) $(call shellquote,$(DESTDIR)$(bindir))
|
||||
$(MAKE) -C templates install
|
||||
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
||||
$(INSTALL) $(PYMODULES) $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
||||
@ -425,20 +458,20 @@ install-doc:
|
||||
|
||||
### Maintainer's dist rules
|
||||
|
||||
git-core.spec: git-core.spec.in Makefile
|
||||
git.spec: git.spec.in Makefile
|
||||
sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@
|
||||
|
||||
GIT_TARNAME=git-core-$(GIT_VERSION)
|
||||
dist: git-core.spec git-tar-tree
|
||||
GIT_TARNAME=git-$(GIT_VERSION)
|
||||
dist: git.spec git-tar-tree
|
||||
./git-tar-tree HEAD $(GIT_TARNAME) > $(GIT_TARNAME).tar
|
||||
@mkdir -p $(GIT_TARNAME)
|
||||
@cp git-core.spec $(GIT_TARNAME)
|
||||
$(TAR) rf $(GIT_TARNAME).tar $(GIT_TARNAME)/git-core.spec
|
||||
@cp git.spec $(GIT_TARNAME)
|
||||
$(TAR) rf $(GIT_TARNAME).tar $(GIT_TARNAME)/git.spec
|
||||
@rm -rf $(GIT_TARNAME)
|
||||
gzip -f -9 $(GIT_TARNAME).tar
|
||||
|
||||
rpm: dist
|
||||
$(RPMBUILD) -ta git-core-$(GIT_VERSION).tar.gz
|
||||
$(RPMBUILD) -ta $(GIT_TARNAME).tar.gz
|
||||
|
||||
deb: dist
|
||||
rm -rf $(GIT_TARNAME)
|
||||
@ -449,13 +482,14 @@ deb: dist
|
||||
### Cleaning rules
|
||||
|
||||
clean:
|
||||
rm -f *.o mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS) $(LIB_FILE)
|
||||
rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(LIB_FILE)
|
||||
rm -f $(PROGRAMS) $(SIMPLE_PROGRAMS) git$X
|
||||
rm -f $(filter-out gitk,$(SCRIPTS))
|
||||
rm -f git-core.spec *.pyc *.pyo
|
||||
rm -f *.spec *.pyc *.pyo
|
||||
rm -rf $(GIT_TARNAME)
|
||||
rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
|
||||
rm -f git-core_$(GIT_VERSION)-*.deb git-core_$(GIT_VERSION)-*.dsc
|
||||
rm -f git-tk_$(GIT_VERSION)-*.deb
|
||||
rm -f git-core_$(GIT_VERSION)-*.dsc
|
||||
rm -f git-*_$(GIT_VERSION)-*.deb
|
||||
$(MAKE) -C Documentation/ clean
|
||||
$(MAKE) -C templates clean
|
||||
$(MAKE) -C t/ clean
|
||||
|
6
README
6
README
@ -396,8 +396,8 @@ git-commit-tree will return the name of the object that represents
|
||||
that commit, and you should save it away for later use. Normally,
|
||||
you'd commit a new `HEAD` state, and while git doesn't care where you
|
||||
save the note about that state, in practice we tend to just write the
|
||||
result to the file `.git/HEAD`, so that we can always see what the
|
||||
last committed state was.
|
||||
result to the file pointed at by `.git/HEAD`, so that we can always see
|
||||
what the last committed state was.
|
||||
|
||||
Here is an ASCII art by Jon Loeliger that illustrates how
|
||||
various pieces fit together.
|
||||
@ -464,7 +464,7 @@ tend to be small and fairly self-explanatory. In particular, if you
|
||||
follow the convention of having the top commit name in `.git/HEAD`,
|
||||
you can do
|
||||
|
||||
git-cat-file commit $(cat .git/HEAD)
|
||||
git-cat-file commit HEAD
|
||||
|
||||
to see what the top commit was.
|
||||
|
||||
|
137
apply.c
137
apply.c
@ -16,6 +16,7 @@
|
||||
// --numstat does numeric diffstat, and doesn't actually apply
|
||||
// --index-info shows the old and new index info for paths if available.
|
||||
//
|
||||
static int allow_binary_replacement = 0;
|
||||
static int check_index = 0;
|
||||
static int write_index = 0;
|
||||
static int diffstat = 0;
|
||||
@ -23,10 +24,11 @@ static int numstat = 0;
|
||||
static int summary = 0;
|
||||
static int check = 0;
|
||||
static int apply = 1;
|
||||
static int no_add = 0;
|
||||
static int show_index_info = 0;
|
||||
static int line_termination = '\n';
|
||||
static const char apply_usage[] =
|
||||
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--index-info] [-z] <patch>...";
|
||||
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] <patch>...";
|
||||
|
||||
/*
|
||||
* For "diff-stat" like behaviour, we keep track of the biggest change
|
||||
@ -53,7 +55,7 @@ struct fragment {
|
||||
struct patch {
|
||||
char *new_name, *old_name, *def_name;
|
||||
unsigned int old_mode, new_mode;
|
||||
int is_rename, is_copy, is_new, is_delete;
|
||||
int is_rename, is_copy, is_new, is_delete, is_binary;
|
||||
int lines_added, lines_deleted;
|
||||
int score;
|
||||
struct fragment *fragments;
|
||||
@ -369,7 +371,7 @@ static int gitdiff_index(const char *line, struct patch *patch)
|
||||
int len;
|
||||
|
||||
ptr = strchr(line, '.');
|
||||
if (!ptr || ptr[1] != '.' || 40 <= ptr - line)
|
||||
if (!ptr || ptr[1] != '.' || 40 < ptr - line)
|
||||
return 0;
|
||||
len = ptr - line;
|
||||
memcpy(patch->old_sha1_prefix, line, len);
|
||||
@ -383,7 +385,7 @@ static int gitdiff_index(const char *line, struct patch *patch)
|
||||
ptr = eol;
|
||||
len = ptr - line;
|
||||
|
||||
if (40 <= len)
|
||||
if (40 < len)
|
||||
return 0;
|
||||
memcpy(patch->new_sha1_prefix, line, len);
|
||||
patch->new_sha1_prefix[len] = 0;
|
||||
@ -890,8 +892,36 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
|
||||
|
||||
patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch);
|
||||
|
||||
if (!patchsize && !metadata_changes(patch))
|
||||
die("patch with only garbage at line %d", linenr);
|
||||
if (!patchsize) {
|
||||
static const char *binhdr[] = {
|
||||
"Binary files ",
|
||||
"Files ",
|
||||
NULL,
|
||||
};
|
||||
int i;
|
||||
int hd = hdrsize + offset;
|
||||
unsigned long llen = linelen(buffer + hd, size - hd);
|
||||
|
||||
if (!memcmp(" differ\n", buffer + hd + llen - 8, 8))
|
||||
for (i = 0; binhdr[i]; i++) {
|
||||
int len = strlen(binhdr[i]);
|
||||
if (len < size - hd &&
|
||||
!memcmp(binhdr[i], buffer + hd, len)) {
|
||||
patch->is_binary = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Empty patch cannot be applied if:
|
||||
* - it is a binary patch and we do not do binary_replace, or
|
||||
* - text patch without metadata change
|
||||
*/
|
||||
if ((apply || check) &&
|
||||
(patch->is_binary
|
||||
? !allow_binary_replacement
|
||||
: !metadata_changes(patch)))
|
||||
die("patch with only garbage at line %d", linenr);
|
||||
}
|
||||
|
||||
return offset + hdrsize + patchsize;
|
||||
}
|
||||
@ -949,9 +979,12 @@ static void show_stats(struct patch *patch)
|
||||
add = (add * max + max_change / 2) / max_change;
|
||||
del = total - add;
|
||||
}
|
||||
printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
|
||||
len, name, patch->lines_added + patch->lines_deleted,
|
||||
add, pluses, del, minuses);
|
||||
if (patch->is_binary)
|
||||
printf(" %s%-*s | Bin\n", prefix, len, name);
|
||||
else
|
||||
printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
|
||||
len, name, patch->lines_added + patch->lines_deleted,
|
||||
add, pluses, del, minuses);
|
||||
if (qname)
|
||||
free(qname);
|
||||
}
|
||||
@ -1099,8 +1132,10 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
|
||||
break;
|
||||
/* Fall-through for ' ' */
|
||||
case '+':
|
||||
memcpy(new + newsize, patch + 1, plen);
|
||||
newsize += plen;
|
||||
if (*patch != '+' || !no_add) {
|
||||
memcpy(new + newsize, patch + 1, plen);
|
||||
newsize += plen;
|
||||
}
|
||||
break;
|
||||
case '@': case '\\':
|
||||
/* Ignore it, we already handled it */
|
||||
@ -1138,10 +1173,77 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
|
||||
static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
|
||||
{
|
||||
struct fragment *frag = patch->fragments;
|
||||
const char *name = patch->old_name ? patch->old_name : patch->new_name;
|
||||
|
||||
if (patch->is_binary) {
|
||||
unsigned char sha1[20];
|
||||
|
||||
if (!allow_binary_replacement)
|
||||
return error("cannot apply binary patch to '%s' "
|
||||
"without --allow-binary-replacement",
|
||||
name);
|
||||
|
||||
/* For safety, we require patch index line to contain
|
||||
* full 40-byte textual SHA1 for old and new, at least for now.
|
||||
*/
|
||||
if (strlen(patch->old_sha1_prefix) != 40 ||
|
||||
strlen(patch->new_sha1_prefix) != 40 ||
|
||||
get_sha1_hex(patch->old_sha1_prefix, sha1) ||
|
||||
get_sha1_hex(patch->new_sha1_prefix, sha1))
|
||||
return error("cannot apply binary patch to '%s' "
|
||||
"without full index line", name);
|
||||
|
||||
if (patch->old_name) {
|
||||
unsigned char hdr[50];
|
||||
int hdrlen;
|
||||
|
||||
/* See if the old one matches what the patch
|
||||
* applies to.
|
||||
*/
|
||||
write_sha1_file_prepare(desc->buffer, desc->size,
|
||||
"blob", sha1, hdr, &hdrlen);
|
||||
if (strcmp(sha1_to_hex(sha1), patch->old_sha1_prefix))
|
||||
return error("the patch applies to '%s' (%s), "
|
||||
"which does not match the "
|
||||
"current contents.",
|
||||
name, sha1_to_hex(sha1));
|
||||
}
|
||||
else {
|
||||
/* Otherwise, the old one must be empty. */
|
||||
if (desc->size)
|
||||
return error("the patch applies to an empty "
|
||||
"'%s' but it is not empty", name);
|
||||
}
|
||||
|
||||
/* For now, we do not record post-image data in the patch,
|
||||
* and require the object already present in the recipient's
|
||||
* object database.
|
||||
*/
|
||||
if (desc->buffer) {
|
||||
free(desc->buffer);
|
||||
desc->alloc = desc->size = 0;
|
||||
}
|
||||
get_sha1_hex(patch->new_sha1_prefix, sha1);
|
||||
|
||||
if (memcmp(sha1, null_sha1, 20)) {
|
||||
char type[10];
|
||||
unsigned long size;
|
||||
|
||||
desc->buffer = read_sha1_file(sha1, type, &size);
|
||||
if (!desc->buffer)
|
||||
return error("the necessary postimage %s for "
|
||||
"'%s' does not exist",
|
||||
patch->new_sha1_prefix, name);
|
||||
desc->alloc = desc->size = size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (frag) {
|
||||
if (apply_one_fragment(desc, frag) < 0)
|
||||
return error("patch failed: %s:%ld", patch->old_name, frag->oldpos);
|
||||
return error("patch failed: %s:%ld",
|
||||
name, frag->oldpos);
|
||||
frag = frag->next;
|
||||
}
|
||||
return 0;
|
||||
@ -1183,6 +1285,7 @@ static int check_patch(struct patch *patch)
|
||||
struct stat st;
|
||||
const char *old_name = patch->old_name;
|
||||
const char *new_name = patch->new_name;
|
||||
const char *name = old_name ? old_name : new_name;
|
||||
|
||||
if (old_name) {
|
||||
int changed;
|
||||
@ -1257,7 +1360,7 @@ static int check_patch(struct patch *patch)
|
||||
}
|
||||
|
||||
if (apply_data(patch, &st) < 0)
|
||||
return error("%s: patch does not apply", old_name);
|
||||
return error("%s: patch does not apply", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1697,11 +1800,19 @@ int main(int argc, char **argv)
|
||||
excludes = x;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--no-add")) {
|
||||
no_add = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--stat")) {
|
||||
apply = 0;
|
||||
diffstat = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--allow-binary-replacement")) {
|
||||
allow_binary_replacement = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--numstat")) {
|
||||
apply = 0;
|
||||
numstat = 1;
|
||||
|
11
cache.h
11
cache.h
@ -179,6 +179,8 @@ extern int commit_index_file(struct cache_file *);
|
||||
extern void rollback_index_file(struct cache_file *);
|
||||
|
||||
extern int trust_executable_bit;
|
||||
extern int only_use_symrefs;
|
||||
extern int diff_rename_limit_default;
|
||||
|
||||
#define MTIME_CHANGED 0x0001
|
||||
#define CTIME_CHANGED 0x0002
|
||||
@ -201,6 +203,7 @@ int git_mkstemp(char *path, size_t n, const char *template);
|
||||
|
||||
int safe_create_leading_directories(char *path);
|
||||
char *safe_strncpy(char *, const char *, size_t);
|
||||
char *enter_repo(char *path, int strict);
|
||||
|
||||
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
|
||||
extern int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void *buffer, unsigned long size);
|
||||
@ -257,11 +260,11 @@ extern void *read_object_with_reference(const unsigned char *sha1,
|
||||
const char *show_date(unsigned long time, int timezone);
|
||||
int parse_date(const char *date, char *buf, int bufsize);
|
||||
void datestamp(char *buf, int bufsize);
|
||||
unsigned long approxidate(const char *);
|
||||
|
||||
extern int setup_ident(void);
|
||||
extern char *get_ident(const char *name, const char *email, const char *date_str);
|
||||
extern char *git_author_info(void);
|
||||
extern char *git_committer_info(void);
|
||||
extern const char *git_author_info(void);
|
||||
extern const char *git_committer_info(void);
|
||||
|
||||
static inline void *xmalloc(size_t size)
|
||||
{
|
||||
@ -383,6 +386,8 @@ extern int git_default_config(const char *, const char *);
|
||||
extern int git_config(config_fn_t fn);
|
||||
extern int git_config_int(const char *, const char *);
|
||||
extern int git_config_bool(const char *, const char *);
|
||||
extern int git_config_set(const char *, const char *);
|
||||
extern int git_config_set_multivar(const char *, const char *, const char *, int);
|
||||
|
||||
#define MAX_GITNAME (1000)
|
||||
extern char git_default_email[MAX_GITNAME];
|
||||
|
61
commit.c
61
commit.c
@ -34,6 +34,8 @@ enum cmit_fmt get_commit_format(const char *arg)
|
||||
return CMIT_FMT_SHORT;
|
||||
if (!strcmp(arg, "=full"))
|
||||
return CMIT_FMT_FULL;
|
||||
if (!strcmp(arg, "=fuller"))
|
||||
return CMIT_FMT_FULLER;
|
||||
if (!strcmp(arg, "=oneline"))
|
||||
return CMIT_FMT_ONELINE;
|
||||
die("invalid --pretty format");
|
||||
@ -202,6 +204,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
||||
unsigned char parent[20];
|
||||
struct commit_list **pptr;
|
||||
struct commit_graft *graft;
|
||||
unsigned n_refs = 0;
|
||||
|
||||
if (item->object.parsed)
|
||||
return 0;
|
||||
@ -212,7 +215,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
||||
return error("bad tree pointer in commit %s\n", sha1_to_hex(item->object.sha1));
|
||||
item->tree = lookup_tree(parent);
|
||||
if (item->tree)
|
||||
add_ref(&item->object, &item->tree->object);
|
||||
n_refs++;
|
||||
bufptr += 46; /* "tree " + "hex sha1" + "\n" */
|
||||
pptr = &item->parents;
|
||||
|
||||
@ -228,7 +231,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
||||
new_parent = lookup_commit(parent);
|
||||
if (new_parent) {
|
||||
pptr = &commit_list_insert(new_parent, pptr)->next;
|
||||
add_ref(&item->object, &new_parent->object);
|
||||
n_refs++;
|
||||
}
|
||||
}
|
||||
if (graft) {
|
||||
@ -239,10 +242,22 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
||||
if (!new_parent)
|
||||
continue;
|
||||
pptr = &commit_list_insert(new_parent, pptr)->next;
|
||||
add_ref(&item->object, &new_parent->object);
|
||||
n_refs++;
|
||||
}
|
||||
}
|
||||
item->date = parse_commit_date(bufptr);
|
||||
|
||||
if (track_object_refs) {
|
||||
unsigned i = 0;
|
||||
struct commit_list *p;
|
||||
struct object_refs *refs = alloc_object_refs(n_refs);
|
||||
if (item->tree)
|
||||
refs->ref[i++] = &item->tree->object;
|
||||
for (p = item->parents; p; p = p->next)
|
||||
refs->ref[i++] = &p->item->object;
|
||||
set_object_refs(&item->object, refs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -361,6 +376,7 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const c
|
||||
int namelen;
|
||||
unsigned long time;
|
||||
int tz, ret;
|
||||
const char *filler = " ";
|
||||
|
||||
if (fmt == CMIT_FMT_ONELINE)
|
||||
return 0;
|
||||
@ -371,9 +387,20 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const c
|
||||
time = strtoul(date, &date, 10);
|
||||
tz = strtol(date, NULL, 10);
|
||||
|
||||
ret = sprintf(buf, "%s: %.*s\n", what, namelen, line);
|
||||
if (fmt == CMIT_FMT_MEDIUM)
|
||||
ret = sprintf(buf, "%s: %.*s%.*s\n", what,
|
||||
(fmt == CMIT_FMT_FULLER) ? 4 : 0,
|
||||
filler, namelen, line);
|
||||
switch (fmt) {
|
||||
case CMIT_FMT_MEDIUM:
|
||||
ret += sprintf(buf + ret, "Date: %s\n", show_date(time, tz));
|
||||
break;
|
||||
case CMIT_FMT_FULLER:
|
||||
ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz));
|
||||
break;
|
||||
default:
|
||||
/* notin' */
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -448,12 +475,21 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg, unsigned l
|
||||
die("bad parent line in commit");
|
||||
offset += add_parent_info(fmt, buf + offset, line, ++parents);
|
||||
}
|
||||
|
||||
/*
|
||||
* MEDIUM == DEFAULT shows only author with dates.
|
||||
* FULL shows both authors but not dates.
|
||||
* FULLER shows both authors and dates.
|
||||
*/
|
||||
if (!memcmp(line, "author ", 7))
|
||||
offset += add_user_info("Author", fmt, buf + offset, line + 7);
|
||||
if (fmt == CMIT_FMT_FULL) {
|
||||
if (!memcmp(line, "committer ", 10))
|
||||
offset += add_user_info("Commit", fmt, buf + offset, line + 10);
|
||||
}
|
||||
offset += add_user_info("Author", fmt,
|
||||
buf + offset,
|
||||
line + 7);
|
||||
if (!memcmp(line, "committer ", 10) &&
|
||||
(fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER))
|
||||
offset += add_user_info("Commit", fmt,
|
||||
buf + offset,
|
||||
line + 10);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -513,7 +549,7 @@ int count_parents(struct commit * commit)
|
||||
void sort_in_topological_order(struct commit_list ** list)
|
||||
{
|
||||
struct commit_list * next = *list;
|
||||
struct commit_list * work = NULL;
|
||||
struct commit_list * work = NULL, **insert;
|
||||
struct commit_list ** pptr = list;
|
||||
struct sort_node * nodes;
|
||||
struct sort_node * next_nodes;
|
||||
@ -557,11 +593,12 @@ void sort_in_topological_order(struct commit_list ** list)
|
||||
* the tips serve as a starting set for the work queue.
|
||||
*/
|
||||
next=*list;
|
||||
insert = &work;
|
||||
while (next) {
|
||||
struct sort_node * node = (struct sort_node *)next->item->object.util;
|
||||
|
||||
if (node->indegree == 0) {
|
||||
commit_list_insert(next->item, &work);
|
||||
insert = &commit_list_insert(next->item, insert)->next;
|
||||
}
|
||||
next=next->next;
|
||||
}
|
||||
|
1
commit.h
1
commit.h
@ -43,6 +43,7 @@ enum cmit_fmt {
|
||||
CMIT_FMT_DEFAULT = CMIT_FMT_MEDIUM,
|
||||
CMIT_FMT_SHORT,
|
||||
CMIT_FMT_FULL,
|
||||
CMIT_FMT_FULLER,
|
||||
CMIT_FMT_ONELINE,
|
||||
};
|
||||
|
||||
|
340
config.c
340
config.c
@ -1,5 +1,12 @@
|
||||
|
||||
/*
|
||||
* GIT - The information manager from hell
|
||||
*
|
||||
* Copyright (C) Linus Torvalds, 2005
|
||||
* Copyright (C) Johannes Schindelin, 2005
|
||||
*
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include <regex.h>
|
||||
|
||||
#define MAXNAME (256)
|
||||
|
||||
@ -136,7 +143,7 @@ static int get_base_var(char *name)
|
||||
return -1;
|
||||
if (c == ']')
|
||||
return baselen;
|
||||
if (!isalnum(c))
|
||||
if (!isalnum(c) && c != '.')
|
||||
return -1;
|
||||
if (baselen > MAXNAME / 2)
|
||||
return -1;
|
||||
@ -214,6 +221,11 @@ int git_default_config(const char *var, const char *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(var, "core.symrefsonly")) {
|
||||
only_use_symrefs = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(var, "user.name")) {
|
||||
strncpy(git_default_name, value, sizeof(git_default_name));
|
||||
return 0;
|
||||
@ -242,3 +254,327 @@ int git_config(config_fn_t fn)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find all the stuff for git_config_set() below.
|
||||
*/
|
||||
|
||||
#define MAX_MATCHES 512
|
||||
|
||||
static struct {
|
||||
int baselen;
|
||||
char* key;
|
||||
int do_not_match;
|
||||
regex_t* value_regex;
|
||||
int multi_replace;
|
||||
off_t offset[MAX_MATCHES];
|
||||
enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
|
||||
int seen;
|
||||
} store;
|
||||
|
||||
static int matches(const char* key, const char* value)
|
||||
{
|
||||
return !strcmp(key, store.key) &&
|
||||
(store.value_regex == NULL ||
|
||||
(store.do_not_match ^
|
||||
!regexec(store.value_regex, value, 0, NULL, 0)));
|
||||
}
|
||||
|
||||
static int store_aux(const char* key, const char* value)
|
||||
{
|
||||
switch (store.state) {
|
||||
case KEY_SEEN:
|
||||
if (matches(key, value)) {
|
||||
if (store.seen == 1 && store.multi_replace == 0) {
|
||||
fprintf(stderr,
|
||||
"Warning: %s has multiple values\n",
|
||||
key);
|
||||
} else if (store.seen >= MAX_MATCHES) {
|
||||
fprintf(stderr, "Too many matches\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
store.offset[store.seen] = ftell(config_file);
|
||||
store.seen++;
|
||||
}
|
||||
break;
|
||||
case SECTION_SEEN:
|
||||
if (strncmp(key, store.key, store.baselen+1)) {
|
||||
store.state = SECTION_END_SEEN;
|
||||
break;
|
||||
} else
|
||||
/* do not increment matches: this is no match */
|
||||
store.offset[store.seen] = ftell(config_file);
|
||||
/* fallthru */
|
||||
case SECTION_END_SEEN:
|
||||
case START:
|
||||
if (matches(key, value)) {
|
||||
store.offset[store.seen] = ftell(config_file);
|
||||
store.state = KEY_SEEN;
|
||||
store.seen++;
|
||||
} else if(!strncmp(key, store.key, store.baselen))
|
||||
store.state = SECTION_SEEN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void store_write_section(int fd, const char* key)
|
||||
{
|
||||
write(fd, "[", 1);
|
||||
write(fd, key, store.baselen);
|
||||
write(fd, "]\n", 2);
|
||||
}
|
||||
|
||||
static void store_write_pair(int fd, const char* key, const char* value)
|
||||
{
|
||||
int i;
|
||||
|
||||
write(fd, "\t", 1);
|
||||
write(fd, key+store.baselen+1,
|
||||
strlen(key+store.baselen+1));
|
||||
write(fd, " = ", 3);
|
||||
for (i = 0; value[i]; i++)
|
||||
switch (value[i]) {
|
||||
case '\n': write(fd, "\\n", 2); break;
|
||||
case '\t': write(fd, "\\t", 2); break;
|
||||
case '"': case '\\': write(fd, "\\", 1);
|
||||
default: write(fd, value+i, 1);
|
||||
}
|
||||
write(fd, "\n", 1);
|
||||
}
|
||||
|
||||
static int find_beginning_of_line(const char* contents, int size,
|
||||
int offset_, int* found_bracket)
|
||||
{
|
||||
int equal_offset = size, bracket_offset = size;
|
||||
int offset;
|
||||
|
||||
for (offset = offset_-2; offset > 0
|
||||
&& contents[offset] != '\n'; offset--)
|
||||
switch (contents[offset]) {
|
||||
case '=': equal_offset = offset; break;
|
||||
case ']': bracket_offset = offset; break;
|
||||
}
|
||||
if (bracket_offset < equal_offset) {
|
||||
*found_bracket = 1;
|
||||
offset = bracket_offset+1;
|
||||
} else
|
||||
offset++;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
int git_config_set(const char* key, const char* value)
|
||||
{
|
||||
return git_config_set_multivar(key, value, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If value==NULL, unset in (remove from) config,
|
||||
* if value_regex!=NULL, disregard key/value pairs where value does not match.
|
||||
* if multi_replace==0, nothing, or only one matching key/value is replaced,
|
||||
* else all matching key/values (regardless how many) are removed,
|
||||
* before the new pair is written.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*
|
||||
* This function does this:
|
||||
*
|
||||
* - it locks the config file by creating ".git/config.lock"
|
||||
*
|
||||
* - it then parses the config using store_aux() as validator to find
|
||||
* the position on the key/value pair to replace. If it is to be unset,
|
||||
* it must be found exactly once.
|
||||
*
|
||||
* - the config file is mmap()ed and the part before the match (if any) is
|
||||
* written to the lock file, then the changed part and the rest.
|
||||
*
|
||||
* - the config file is removed and the lock file rename()d to it.
|
||||
*
|
||||
*/
|
||||
int git_config_set_multivar(const char* key, const char* value,
|
||||
const char* value_regex, int multi_replace)
|
||||
{
|
||||
int i;
|
||||
struct stat st;
|
||||
int fd;
|
||||
char* config_filename = strdup(git_path("config"));
|
||||
char* lock_file = strdup(git_path("config.lock"));
|
||||
const char* last_dot = strrchr(key, '.');
|
||||
|
||||
/*
|
||||
* Since "key" actually contains the section name and the real
|
||||
* key name separated by a dot, we have to know where the dot is.
|
||||
*/
|
||||
|
||||
if (last_dot == NULL) {
|
||||
fprintf(stderr, "key does not contain a section: %s\n", key);
|
||||
return 2;
|
||||
}
|
||||
store.baselen = last_dot - key;
|
||||
|
||||
store.multi_replace = multi_replace;
|
||||
|
||||
/*
|
||||
* Validate the key and while at it, lower case it for matching.
|
||||
*/
|
||||
store.key = (char*)malloc(strlen(key)+1);
|
||||
for (i = 0; key[i]; i++)
|
||||
if (i != store.baselen &&
|
||||
((!isalnum(key[i]) && key[i] != '.') ||
|
||||
(i == store.baselen+1 && !isalpha(key[i])))) {
|
||||
fprintf(stderr, "invalid key: %s\n", key);
|
||||
free(store.key);
|
||||
return 1;
|
||||
} else
|
||||
store.key[i] = tolower(key[i]);
|
||||
store.key[i] = 0;
|
||||
|
||||
/*
|
||||
* The lock_file serves a purpose in addition to locking: the new
|
||||
* contents of .git/config will be written into it.
|
||||
*/
|
||||
fd = open(lock_file, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "could not lock config file\n");
|
||||
free(store.key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If .git/config does not exist yet, write a minimal version.
|
||||
*/
|
||||
if (stat(config_filename, &st)) {
|
||||
static const char contents[] =
|
||||
"#\n"
|
||||
"# This is the config file\n"
|
||||
"#\n"
|
||||
"\n";
|
||||
|
||||
free(store.key);
|
||||
|
||||
/* if nothing to unset, error out */
|
||||
if (value == NULL) {
|
||||
close(fd);
|
||||
unlink(lock_file);
|
||||
return 5;
|
||||
}
|
||||
|
||||
store.key = (char*)key;
|
||||
|
||||
write(fd, contents, sizeof(contents)-1);
|
||||
store_write_section(fd, key);
|
||||
store_write_pair(fd, key, value);
|
||||
} else{
|
||||
int in_fd;
|
||||
char* contents;
|
||||
int i, copy_begin, copy_end, new_line = 0;
|
||||
|
||||
if (value_regex == NULL)
|
||||
store.value_regex = NULL;
|
||||
else {
|
||||
if (value_regex[0] == '!') {
|
||||
store.do_not_match = 1;
|
||||
value_regex++;
|
||||
} else
|
||||
store.do_not_match = 0;
|
||||
|
||||
store.value_regex = (regex_t*)malloc(sizeof(regex_t));
|
||||
if (regcomp(store.value_regex, value_regex,
|
||||
REG_EXTENDED)) {
|
||||
fprintf(stderr, "Invalid pattern: %s",
|
||||
value_regex);
|
||||
free(store.value_regex);
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
store.offset[0] = 0;
|
||||
store.state = START;
|
||||
store.seen = 0;
|
||||
|
||||
/*
|
||||
* After this, store.offset will contain the *end* offset
|
||||
* of the last match, or remain at 0 if no match was found.
|
||||
* As a side effect, we make sure to transform only a valid
|
||||
* existing config file.
|
||||
*/
|
||||
if (git_config(store_aux)) {
|
||||
fprintf(stderr, "invalid config file\n");
|
||||
free(store.key);
|
||||
if (store.value_regex != NULL) {
|
||||
regfree(store.value_regex);
|
||||
free(store.value_regex);
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
free(store.key);
|
||||
if (store.value_regex != NULL) {
|
||||
regfree(store.value_regex);
|
||||
free(store.value_regex);
|
||||
}
|
||||
|
||||
/* if nothing to unset, or too many matches, error out */
|
||||
if ((store.seen == 0 && value == NULL) ||
|
||||
(store.seen > 1 && multi_replace == 0)) {
|
||||
close(fd);
|
||||
unlink(lock_file);
|
||||
return 5;
|
||||
}
|
||||
|
||||
in_fd = open(config_filename, O_RDONLY, 0666);
|
||||
contents = mmap(NULL, st.st_size, PROT_READ,
|
||||
MAP_PRIVATE, in_fd, 0);
|
||||
close(in_fd);
|
||||
|
||||
if (store.seen == 0)
|
||||
store.seen = 1;
|
||||
|
||||
for (i = 0, copy_begin = 0; i < store.seen; i++) {
|
||||
if (store.offset[i] == 0) {
|
||||
store.offset[i] = copy_end = st.st_size;
|
||||
} else if (store.state != KEY_SEEN) {
|
||||
copy_end = store.offset[i];
|
||||
} else
|
||||
copy_end = find_beginning_of_line(
|
||||
contents, st.st_size,
|
||||
store.offset[i]-2, &new_line);
|
||||
|
||||
/* write the first part of the config */
|
||||
if (copy_end > copy_begin) {
|
||||
write(fd, contents + copy_begin,
|
||||
copy_end - copy_begin);
|
||||
if (new_line)
|
||||
write(fd, "\n", 1);
|
||||
}
|
||||
copy_begin = store.offset[i];
|
||||
}
|
||||
|
||||
/* write the pair (value == NULL means unset) */
|
||||
if (value != NULL) {
|
||||
if (store.state == START)
|
||||
store_write_section(fd, key);
|
||||
store_write_pair(fd, key, value);
|
||||
}
|
||||
|
||||
/* write the rest of the config */
|
||||
if (copy_begin < st.st_size)
|
||||
write(fd, contents + copy_begin,
|
||||
st.st_size - copy_begin);
|
||||
|
||||
munmap(contents, st.st_size);
|
||||
unlink(config_filename);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
if (rename(lock_file, config_filename) < 0) {
|
||||
fprintf(stderr, "Could not rename the lock file?\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
166
connect.c
166
connect.c
@ -427,7 +427,7 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sa.sin_family = he->h_addrtype;
|
||||
sa.sin_port = htons(nport);
|
||||
memcpy(&sa.sin_addr, ap, he->h_length);
|
||||
memcpy(&sa.sin_addr, *ap, he->h_length);
|
||||
|
||||
if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
|
||||
close(sockfd);
|
||||
@ -448,42 +448,162 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
|
||||
|
||||
#endif /* NO_IPV6 */
|
||||
|
||||
static char *git_proxy_command = NULL;
|
||||
static const char *rhost_name = NULL;
|
||||
static int rhost_len;
|
||||
|
||||
static int git_proxy_command_options(const char *var, const char *value)
|
||||
{
|
||||
if (!strcmp(var, "core.gitproxy")) {
|
||||
const char *for_pos;
|
||||
int matchlen = -1;
|
||||
int hostlen;
|
||||
|
||||
if (git_proxy_command)
|
||||
return 0;
|
||||
/* [core]
|
||||
* ;# matches www.kernel.org as well
|
||||
* gitproxy = netcatter-1 for kernel.org
|
||||
* gitproxy = netcatter-2 for sample.xz
|
||||
* gitproxy = netcatter-default
|
||||
*/
|
||||
for_pos = strstr(value, " for ");
|
||||
if (!for_pos)
|
||||
/* matches everybody */
|
||||
matchlen = strlen(value);
|
||||
else {
|
||||
hostlen = strlen(for_pos + 5);
|
||||
if (rhost_len < hostlen)
|
||||
matchlen = -1;
|
||||
else if (!strncmp(for_pos + 5,
|
||||
rhost_name + rhost_len - hostlen,
|
||||
hostlen) &&
|
||||
((rhost_len == hostlen) ||
|
||||
rhost_name[rhost_len - hostlen -1] == '.'))
|
||||
matchlen = for_pos - value;
|
||||
else
|
||||
matchlen = -1;
|
||||
}
|
||||
if (0 <= matchlen) {
|
||||
/* core.gitproxy = none for kernel.org */
|
||||
if (matchlen == 4 &&
|
||||
!memcmp(value, "none", 4))
|
||||
matchlen = 0;
|
||||
git_proxy_command = xmalloc(matchlen + 1);
|
||||
memcpy(git_proxy_command, value, matchlen);
|
||||
git_proxy_command[matchlen] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_default_config(var, value);
|
||||
}
|
||||
|
||||
static int git_use_proxy(const char *host)
|
||||
{
|
||||
rhost_name = host;
|
||||
rhost_len = strlen(host);
|
||||
git_proxy_command = getenv("GIT_PROXY_COMMAND");
|
||||
git_config(git_proxy_command_options);
|
||||
rhost_name = NULL;
|
||||
return (git_proxy_command && *git_proxy_command);
|
||||
}
|
||||
|
||||
static int git_proxy_connect(int fd[2], const char *prog, char *host, char *path)
|
||||
{
|
||||
char *port = STR(DEFAULT_GIT_PORT);
|
||||
char *colon, *end;
|
||||
int pipefd[2][2];
|
||||
pid_t pid;
|
||||
|
||||
if (host[0] == '[') {
|
||||
end = strchr(host + 1, ']');
|
||||
if (end) {
|
||||
*end = 0;
|
||||
end++;
|
||||
host++;
|
||||
} else
|
||||
end = host;
|
||||
} else
|
||||
end = host;
|
||||
colon = strchr(end, ':');
|
||||
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
port = colon + 1;
|
||||
}
|
||||
|
||||
if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
|
||||
die("unable to create pipe pair for communication");
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
dup2(pipefd[1][0], 0);
|
||||
dup2(pipefd[0][1], 1);
|
||||
close(pipefd[0][0]);
|
||||
close(pipefd[0][1]);
|
||||
close(pipefd[1][0]);
|
||||
close(pipefd[1][1]);
|
||||
execlp(git_proxy_command, git_proxy_command, host, port, NULL);
|
||||
die("exec failed");
|
||||
}
|
||||
fd[0] = pipefd[0][0];
|
||||
fd[1] = pipefd[1][1];
|
||||
close(pipefd[0][1]);
|
||||
close(pipefd[1][0]);
|
||||
packet_write(fd[1], "%s %s\n", prog, path);
|
||||
return pid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Yeah, yeah, fixme. Need to pass in the heads etc.
|
||||
*/
|
||||
int git_connect(int fd[2], char *url, const char *prog)
|
||||
{
|
||||
char command[1024];
|
||||
char *host, *path;
|
||||
char *colon;
|
||||
char *host, *path = url;
|
||||
char *colon = NULL;
|
||||
int pipefd[2][2];
|
||||
pid_t pid;
|
||||
enum protocol protocol;
|
||||
enum protocol protocol = PROTO_LOCAL;
|
||||
|
||||
host = NULL;
|
||||
path = url;
|
||||
colon = strchr(url, ':');
|
||||
protocol = PROTO_LOCAL;
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
host = strstr(url, "://");
|
||||
if(host) {
|
||||
*host = '\0';
|
||||
protocol = get_protocol(url);
|
||||
host += 3;
|
||||
path = strchr(host, '/');
|
||||
}
|
||||
else {
|
||||
host = url;
|
||||
path = colon+1;
|
||||
protocol = PROTO_SSH;
|
||||
if (!memcmp(path, "//", 2)) {
|
||||
char *slash = strchr(path + 2, '/');
|
||||
if (slash) {
|
||||
int nr = slash - path - 2;
|
||||
memmove(path, path+2, nr);
|
||||
path[nr] = 0;
|
||||
protocol = get_protocol(url);
|
||||
host = path;
|
||||
path = slash;
|
||||
}
|
||||
if ((colon = strchr(host, ':'))) {
|
||||
protocol = PROTO_SSH;
|
||||
*colon = '\0';
|
||||
path = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (protocol == PROTO_GIT)
|
||||
if (!path || !*path)
|
||||
die("No path specified. See 'man git-pull' for valid url syntax");
|
||||
|
||||
/*
|
||||
* null-terminate hostname and point path to ~ for URL's like this:
|
||||
* ssh://host.xz/~user/repo
|
||||
*/
|
||||
if (protocol != PROTO_LOCAL && host != url) {
|
||||
char *ptr = path;
|
||||
if (path[1] == '~')
|
||||
path++;
|
||||
else
|
||||
path = strdup(ptr);
|
||||
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
if (protocol == PROTO_GIT) {
|
||||
if (git_use_proxy(host))
|
||||
return git_proxy_connect(fd, prog, host, path);
|
||||
return git_tcp_connect(fd, prog, host, path);
|
||||
}
|
||||
|
||||
if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
|
||||
die("unable to create pipe pair for communication");
|
||||
|
151
daemon.c
151
daemon.c
@ -15,10 +15,11 @@ static int verbose;
|
||||
|
||||
static const char daemon_usage[] =
|
||||
"git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
|
||||
" [--timeout=n] [--init-timeout=n] [directory...]";
|
||||
" [--timeout=n] [--init-timeout=n] [--strict-paths] [directory...]";
|
||||
|
||||
/* List of acceptable pathname prefixes */
|
||||
static char **ok_paths = NULL;
|
||||
static int strict_paths = 0;
|
||||
|
||||
/* If this is set, git-daemon-export-ok is not required */
|
||||
static int export_all_trees = 0;
|
||||
@ -81,69 +82,52 @@ static void loginfo(const char *err, ...)
|
||||
va_end(params);
|
||||
}
|
||||
|
||||
static int path_ok(const char *dir)
|
||||
static char *path_ok(char *dir)
|
||||
{
|
||||
const char *p = dir;
|
||||
char **pp;
|
||||
int sl, ndot;
|
||||
char *path = enter_repo(dir, strict_paths);
|
||||
|
||||
/* The pathname here should be an absolute path. */
|
||||
if ( *p++ != '/' )
|
||||
return 0;
|
||||
|
||||
sl = 1; ndot = 0;
|
||||
|
||||
for (;;) {
|
||||
if ( *p == '.' ) {
|
||||
ndot++;
|
||||
} else if ( *p == '\0' ) {
|
||||
/* Reject "." and ".." at the end of the path */
|
||||
if ( sl && ndot > 0 && ndot < 3 )
|
||||
return 0;
|
||||
|
||||
/* Otherwise OK */
|
||||
break;
|
||||
} else if ( *p == '/' ) {
|
||||
/* Refuse "", "." or ".." */
|
||||
if ( sl && ndot < 3 )
|
||||
return 0;
|
||||
sl = 1;
|
||||
ndot = 0;
|
||||
} else {
|
||||
sl = ndot = 0;
|
||||
}
|
||||
p++;
|
||||
if (!path) {
|
||||
logerror("'%s': unable to chdir or not a git archive", dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( ok_paths && *ok_paths ) {
|
||||
int ok = 0;
|
||||
int dirlen = strlen(dir);
|
||||
char **pp;
|
||||
int pathlen = strlen(path);
|
||||
|
||||
/* The validation is done on the paths after enter_repo
|
||||
* canonicalization, so whitelist should be written in
|
||||
* terms of real pathnames (i.e. after ~user is expanded
|
||||
* and symlinks resolved).
|
||||
*/
|
||||
for ( pp = ok_paths ; *pp ; pp++ ) {
|
||||
int len = strlen(*pp);
|
||||
if ( len <= dirlen &&
|
||||
!strncmp(*pp, dir, len) &&
|
||||
(dir[len] == '/' || dir[len] == '\0') ) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
if (len <= pathlen &&
|
||||
!memcmp(*pp, path, len) &&
|
||||
(path[len] == '\0' ||
|
||||
(!strict_paths && path[len] == '/')))
|
||||
return path;
|
||||
}
|
||||
|
||||
if ( !ok )
|
||||
return 0; /* Path not in whitelist */
|
||||
}
|
||||
else {
|
||||
/* be backwards compatible */
|
||||
if (!strict_paths)
|
||||
return path;
|
||||
}
|
||||
|
||||
return 1; /* Path acceptable */
|
||||
logerror("'%s': not in whitelist", path);
|
||||
return NULL; /* Fallthrough. Deny by default */
|
||||
}
|
||||
|
||||
static int set_dir(const char *dir)
|
||||
static int upload(char *dir)
|
||||
{
|
||||
if (!path_ok(dir)) {
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
/* Timeout as string */
|
||||
char timeout_buf[64];
|
||||
const char *path;
|
||||
|
||||
if ( chdir(dir) )
|
||||
loginfo("Request for '%s'", dir);
|
||||
|
||||
if (!(path = path_ok(dir)))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
@ -152,45 +136,17 @@ static int set_dir(const char *dir)
|
||||
* We want a readable HEAD, usable "objects" directory, and
|
||||
* a "git-daemon-export-ok" flag that says that the other side
|
||||
* is ok with us doing this.
|
||||
*
|
||||
* path_ok() uses enter_repo() and does whitelist checking.
|
||||
* We only need to make sure the repository is exported.
|
||||
*/
|
||||
|
||||
if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
|
||||
logerror("'%s': repository not exported.", path);
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (access("objects/", X_OK) || access("HEAD", R_OK)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If all this passed, we're OK */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upload(char *dir)
|
||||
{
|
||||
/* Try paths in this order */
|
||||
static const char *paths[] = { "%s", "%s/.git", "%s.git", "%s.git/.git", NULL };
|
||||
const char **pp;
|
||||
/* Enough for the longest path above including final null */
|
||||
int buflen = strlen(dir)+10;
|
||||
char *dirbuf = xmalloc(buflen);
|
||||
/* Timeout as string */
|
||||
char timeout_buf[64];
|
||||
|
||||
loginfo("Request for '%s'", dir);
|
||||
|
||||
for ( pp = paths ; *pp ; pp++ ) {
|
||||
snprintf(dirbuf, buflen, *pp, dir);
|
||||
if ( !set_dir(dirbuf) )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !*pp ) {
|
||||
logerror("Cannot set directory '%s': %s", dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We'll ignore SIGTERM from now on, we have a
|
||||
* good client.
|
||||
@ -216,7 +172,7 @@ static int execute(void)
|
||||
if (len && line[len-1] == '\n')
|
||||
line[--len] = 0;
|
||||
|
||||
if (!strncmp("git-upload-pack /", line, 17))
|
||||
if (!strncmp("git-upload-pack ", line, 16))
|
||||
return upload(line+16);
|
||||
|
||||
logerror("Protocol error: '%s'", line);
|
||||
@ -510,8 +466,14 @@ static int socksetup(int port, int **socklist_p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (listen(sockfd, 5) < 0) {
|
||||
close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*socklist_p = xmalloc(sizeof(int));
|
||||
**socklist_p = sockfd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -594,6 +556,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if (!strcmp(arg, "--inetd")) {
|
||||
inetd_mode = 1;
|
||||
log_syslog = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--verbose")) {
|
||||
@ -602,7 +565,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if (!strcmp(arg, "--syslog")) {
|
||||
log_syslog = 1;
|
||||
openlog("git-daemon", 0, LOG_DAEMON);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--export-all")) {
|
||||
@ -611,9 +573,15 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if (!strncmp(arg, "--timeout=", 10)) {
|
||||
timeout = atoi(arg+10);
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(arg, "--init-timeout=", 15)) {
|
||||
init_timeout = atoi(arg+15);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--strict-paths")) {
|
||||
strict_paths = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--")) {
|
||||
ok_paths = &argv[i+1];
|
||||
@ -626,10 +594,21 @@ int main(int argc, char **argv)
|
||||
usage(daemon_usage);
|
||||
}
|
||||
|
||||
if (log_syslog)
|
||||
openlog("git-daemon", 0, LOG_DAEMON);
|
||||
|
||||
if (strict_paths && (!ok_paths || !*ok_paths)) {
|
||||
if (!inetd_mode)
|
||||
die("git-daemon: option --strict-paths requires a whitelist");
|
||||
|
||||
logerror("option --strict-paths requires a whitelist");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (inetd_mode) {
|
||||
fclose(stderr); //FIXME: workaround
|
||||
return execute();
|
||||
} else {
|
||||
return serve(port);
|
||||
}
|
||||
|
||||
return serve(port);
|
||||
}
|
||||
|
186
date.c
186
date.c
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
@ -33,7 +34,7 @@ static const char *month_names[] = {
|
||||
};
|
||||
|
||||
static const char *weekday_names[] = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
|
||||
"Sundays", "Mondays", "Tuesdays", "Wednesdays", "Thursdays", "Fridays", "Saturdays"
|
||||
};
|
||||
|
||||
/*
|
||||
@ -460,3 +461,186 @@ void datestamp(char *buf, int bufsize)
|
||||
|
||||
date_string(now, offset, buf, bufsize);
|
||||
}
|
||||
|
||||
static void update_tm(struct tm *tm, unsigned long sec)
|
||||
{
|
||||
time_t n = mktime(tm) - sec;
|
||||
localtime_r(&n, tm);
|
||||
}
|
||||
|
||||
static void date_yesterday(struct tm *tm, int *num)
|
||||
{
|
||||
update_tm(tm, 24*60*60);
|
||||
}
|
||||
|
||||
static void date_time(struct tm *tm, int hour)
|
||||
{
|
||||
if (tm->tm_hour < hour)
|
||||
date_yesterday(tm, NULL);
|
||||
tm->tm_hour = hour;
|
||||
tm->tm_min = 0;
|
||||
tm->tm_sec = 0;
|
||||
}
|
||||
|
||||
static void date_midnight(struct tm *tm, int *num)
|
||||
{
|
||||
date_time(tm, 0);
|
||||
}
|
||||
|
||||
static void date_noon(struct tm *tm, int *num)
|
||||
{
|
||||
date_time(tm, 12);
|
||||
}
|
||||
|
||||
static void date_tea(struct tm *tm, int *num)
|
||||
{
|
||||
date_time(tm, 17);
|
||||
}
|
||||
|
||||
static const struct special {
|
||||
const char *name;
|
||||
void (*fn)(struct tm *, int *);
|
||||
} special[] = {
|
||||
{ "yesterday", date_yesterday },
|
||||
{ "noon", date_noon },
|
||||
{ "midnight", date_midnight },
|
||||
{ "tea", date_tea },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const char *number_name[] = {
|
||||
"zero", "one", "two", "three", "four",
|
||||
"five", "six", "seven", "eight", "nine", "ten",
|
||||
};
|
||||
|
||||
static const struct typelen {
|
||||
const char *type;
|
||||
int length;
|
||||
} typelen[] = {
|
||||
{ "seconds", 1 },
|
||||
{ "minutes", 60 },
|
||||
{ "hours", 60*60 },
|
||||
{ "days", 24*60*60 },
|
||||
{ "weeks", 7*24*60*60 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const char *approxidate_alpha(const char *date, struct tm *tm, int *num)
|
||||
{
|
||||
const struct typelen *tl;
|
||||
const struct special *s;
|
||||
const char *end = date;
|
||||
int n = 1, i;
|
||||
|
||||
while (isalpha(*++end))
|
||||
n++;
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
int match = match_string(date, month_names[i]);
|
||||
if (match >= 3) {
|
||||
tm->tm_mon = i;
|
||||
return end;
|
||||
}
|
||||
}
|
||||
|
||||
for (s = special; s->name; s++) {
|
||||
int len = strlen(s->name);
|
||||
if (match_string(date, s->name) == len) {
|
||||
s->fn(tm, num);
|
||||
return end;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*num) {
|
||||
for (i = 1; i < 11; i++) {
|
||||
int len = strlen(number_name[i]);
|
||||
if (match_string(date, number_name[i]) == len) {
|
||||
*num = i;
|
||||
return end;
|
||||
}
|
||||
}
|
||||
if (match_string(date, "last") == 4)
|
||||
*num = 1;
|
||||
return end;
|
||||
}
|
||||
|
||||
tl = typelen;
|
||||
while (tl->type) {
|
||||
int len = strlen(tl->type);
|
||||
if (match_string(date, tl->type) >= len-1) {
|
||||
update_tm(tm, tl->length * *num);
|
||||
*num = 0;
|
||||
return end;
|
||||
}
|
||||
tl++;
|
||||
}
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
int match = match_string(date, weekday_names[i]);
|
||||
if (match >= 3) {
|
||||
int diff, n = *num -1;
|
||||
*num = 0;
|
||||
|
||||
diff = tm->tm_wday - i;
|
||||
if (diff <= 0)
|
||||
n++;
|
||||
diff += 7*n;
|
||||
|
||||
update_tm(tm, diff * 24 * 60 * 60);
|
||||
return end;
|
||||
}
|
||||
}
|
||||
|
||||
if (match_string(date, "months") >= 5) {
|
||||
int n = tm->tm_mon - *num;
|
||||
*num = 0;
|
||||
while (n < 0) {
|
||||
n += 12;
|
||||
tm->tm_year--;
|
||||
}
|
||||
tm->tm_mon = n;
|
||||
return end;
|
||||
}
|
||||
|
||||
if (match_string(date, "years") >= 4) {
|
||||
tm->tm_year -= *num;
|
||||
*num = 0;
|
||||
return end;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
unsigned long approxidate(const char *date)
|
||||
{
|
||||
int number = 0;
|
||||
struct tm tm, now;
|
||||
struct timeval tv;
|
||||
char buffer[50];
|
||||
|
||||
if (parse_date(date, buffer, sizeof(buffer)) > 0)
|
||||
return strtoul(buffer, NULL, 10);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
localtime_r(&tv.tv_sec, &tm);
|
||||
now = tm;
|
||||
for (;;) {
|
||||
unsigned char c = *date;
|
||||
if (!c)
|
||||
break;
|
||||
date++;
|
||||
if (isdigit(c)) {
|
||||
char *end;
|
||||
number = strtoul(date-1, &end, 10);
|
||||
date = end;
|
||||
continue;
|
||||
}
|
||||
if (isalpha(c))
|
||||
date = approxidate_alpha(date-1, &tm, &number);
|
||||
}
|
||||
if (number > 0 && number < 32)
|
||||
tm.tm_mday = number;
|
||||
if (tm.tm_mon > now.tm_mon)
|
||||
tm.tm_year--;
|
||||
return mktime(&tm);
|
||||
}
|
||||
|
69
debian/changelog
vendored
69
debian/changelog
vendored
@ -1,3 +1,45 @@
|
||||
git-core (0.99.9k-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9k but not 1.0rc yet.
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Fri, 25 Nov 2005 16:33:11 -0800
|
||||
|
||||
git-core (0.99.9j-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9j aka 1.0rc3
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Wed, 16 Nov 2005 20:39:55 -0800
|
||||
|
||||
git-core (0.99.9i-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9i aka 1.0rc2
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Mon, 14 Nov 2005 18:38:27 -0800
|
||||
|
||||
git-core (0.99.9h-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9h
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Fri, 11 Nov 2005 22:33:18 -0800
|
||||
|
||||
git-core (0.99.9g-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9g
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Wed, 9 Nov 2005 21:01:55 -0800
|
||||
|
||||
git-core (0.99.9f-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9f
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Tue, 8 Nov 2005 01:21:52 -0800
|
||||
|
||||
git-core (0.99.9e-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9e
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Sun, 6 Nov 2005 18:37:18 -0800
|
||||
|
||||
git-core (0.99.9d-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9d
|
||||
@ -22,6 +64,33 @@ git-core (0.99.9a-0) unstable; urgency=low
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Sun, 30 Oct 2005 15:03:32 -0800
|
||||
|
||||
git-core (0.99.9.GIT-2) unstable; urgency=low
|
||||
|
||||
* Build Dependency did not include libexpat-dev.
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Sun, 13 Nov 2005 01:55:34 -0800
|
||||
|
||||
git-core (0.99.9.GIT-1) unstable; urgency=low
|
||||
|
||||
* Do not scatter txt and html documentation into feature
|
||||
subpackages. Do place man pages into them.
|
||||
* Capture more cvs stuff into git-cvs package.
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Tue, 8 Nov 2005 01:19:06 -0800
|
||||
|
||||
git-core (0.99.9.GIT-0) unstable; urgency=low
|
||||
|
||||
* Test Build.
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Sat, 5 Nov 2005 11:18:13 -0800
|
||||
|
||||
git-core (0.99.9-1) unstable; urgency=low
|
||||
|
||||
* Split the git-core binary package into core, doc, and foreign SCM
|
||||
interoperability modules.
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Sat, 5 Nov 2005 11:18:13 -0800
|
||||
|
||||
git-core (0.99.9-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9
|
||||
|
41
debian/control
vendored
41
debian/control
vendored
@ -2,13 +2,13 @@ Source: git-core
|
||||
Section: devel
|
||||
Priority: optional
|
||||
Maintainer: Junio C Hamano <junkio@cox.net>
|
||||
Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev|libcurl3-gnutls-dev|libcurl3-openssl-dev, asciidoc (>= 6.0.3), xmlto, debhelper (>= 4.0.0), bc
|
||||
Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev|libcurl3-gnutls-dev|libcurl3-openssl-dev, asciidoc (>= 7), xmlto, debhelper (>= 4.0.0), bc, libexpat-dev
|
||||
Standards-Version: 3.6.1
|
||||
|
||||
Package: git-core
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${perl:Depends}, ${misc:Depends}, rcs
|
||||
Recommends: rsync, curl, ssh, libmail-sendmail-perl, libemail-valid-perl, libsvn-core-perl (>= 1.2.1), python (>= 2.4.0), less
|
||||
Recommends: rsync, curl, ssh, python (>= 2.4.0), less
|
||||
Suggests: cogito, patch
|
||||
Conflicts: git, cogito (<< 0.13)
|
||||
Description: The git content addressable filesystem
|
||||
@ -18,9 +18,46 @@ Description: The git content addressable filesystem
|
||||
enables human beings to work with the database in a manner to a degree
|
||||
similar to other SCM tools.
|
||||
|
||||
Package: git-doc
|
||||
Architecture: all
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, git-core
|
||||
Description: The git content addressable filesystem, Documentation
|
||||
This package contains documentation for GIT.
|
||||
|
||||
Package: git-tk
|
||||
Architecture: all
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, git-core, tk8.4
|
||||
Description: The git content addressable filesystem, GUI add-on
|
||||
This package contains 'gitk', the git revision tree visualizer.
|
||||
|
||||
Package: git-svn
|
||||
Architecture: all
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, git-core, libsvn-core-perl (>= 1.2.1)
|
||||
Suggests: subversion
|
||||
Description: The git content addressable filesystem, SVN interoperability
|
||||
This package contains 'git-svnimport', to import development history from
|
||||
SVN repositories.
|
||||
|
||||
Package: git-arch
|
||||
Architecture: all
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, git-core
|
||||
Suggests: tla, bazaar
|
||||
Description: The git content addressable filesystem, GNUArch interoperability
|
||||
This package contains 'git-archimport', to import development history from
|
||||
GNUArch repositories.
|
||||
|
||||
Package: git-cvs
|
||||
Architecture: all
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, git-core, cvsps (>= 2.1)
|
||||
Suggests: cvs
|
||||
Description: The git content addressable filesystem, CVS interoperability
|
||||
This package contains 'git-cvsimport', to import development history from
|
||||
CVS repositories.
|
||||
|
||||
Package: git-email
|
||||
Architecture: all
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, git-core, libmail-sendmail-perl, libemail-valid-perl
|
||||
Description: The git content addressable filesystem, e-mail add-on
|
||||
This package contains 'git-send-email', to send a series of patch e-mails.
|
||||
|
||||
|
||||
|
2
debian/git-arch.files
vendored
Normal file
2
debian/git-arch.files
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/usr/bin/git-arch*
|
||||
/usr/share/man/*/git-arch*
|
4
debian/git-core.doc-base
vendored
4
debian/git-core.doc-base
vendored
@ -6,6 +6,8 @@ Section: Devel
|
||||
Format: HTML
|
||||
Index: /usr/share/doc/git-core/git.html
|
||||
Files: /usr/share/doc/git-core/*.html
|
||||
/usr/share/doc/git-core/*/*.html
|
||||
|
||||
Format: text
|
||||
Files: /usr/share/doc/git-core/git.txt*
|
||||
Files: /usr/share/doc/git-core/*.txt
|
||||
/usr/share/doc/git-core/*/*.txt
|
||||
|
2
debian/git-cvs.files
vendored
Normal file
2
debian/git-cvs.files
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/usr/bin/git-cvs*
|
||||
/usr/share/man/*/git-cvs*
|
4
debian/git-doc.files
vendored
Normal file
4
debian/git-doc.files
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/usr/share/doc/git-core/*.txt
|
||||
/usr/share/doc/git-core/*.html
|
||||
/usr/share/doc/git-core/*/*.html
|
||||
/usr/share/doc/git-core/*/*.txt
|
2
debian/git-email.files
vendored
Normal file
2
debian/git-email.files
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/usr/bin/git-send-email
|
||||
/usr/share/man/*/git-send-email.*
|
2
debian/git-svn.files
vendored
Normal file
2
debian/git-svn.files
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/usr/bin/git-svn*
|
||||
/usr/share/man/*/git-svn*
|
1
debian/git-tk.files
vendored
1
debian/git-tk.files
vendored
@ -1,3 +1,2 @@
|
||||
/usr/bin/gitk
|
||||
/usr/share/man/man1/gitk.*
|
||||
/usr/share/doc/git-core/gitk.*
|
||||
|
11
debian/rules
vendored
11
debian/rules
vendored
@ -41,7 +41,7 @@ MAN_DESTDIR := $(DESTDIR)/$(MANDIR)
|
||||
build: debian/build-stamp
|
||||
debian/build-stamp:
|
||||
dh_testdir
|
||||
$(MAKE) prefix=$(PREFIX) PYTHON_PATH=/usr/bin/python2.4 all doc test
|
||||
$(MAKE) prefix=$(PREFIX) PYTHON_PATH=/usr/bin/python2.4 all test doc
|
||||
touch debian/build-stamp
|
||||
|
||||
debian-clean:
|
||||
@ -62,10 +62,15 @@ install: build
|
||||
make DESTDIR=$(DESTDIR) prefix=$(PREFIX) mandir=$(MANDIR) \
|
||||
install install-doc
|
||||
|
||||
mkdir -p $(DOC_DESTDIR)
|
||||
find $(DOC) '(' -name '*.txt' -o -name '*.html' ')' -exec install {} $(DOC_DESTDIR) ';'
|
||||
make -C Documentation DESTDIR=$(DESTDIR) prefix=$(PREFIX) \
|
||||
WEBDOC_DEST=$(DOC_DESTDIR) install-webdoc
|
||||
|
||||
dh_movefiles -p git-arch
|
||||
dh_movefiles -p git-cvs
|
||||
dh_movefiles -p git-svn
|
||||
dh_movefiles -p git-tk
|
||||
dh_movefiles -p git-email
|
||||
dh_movefiles -p git-doc
|
||||
dh_movefiles -p git-core
|
||||
find debian/tmp -type d -o -print | sed -e 's/^/? /'
|
||||
|
||||
|
@ -38,7 +38,7 @@ int main(int argc, const char **argv)
|
||||
const char *prefix = setup_git_directory();
|
||||
int entries, i;
|
||||
|
||||
git_config(git_default_config);
|
||||
git_config(git_diff_config);
|
||||
diff_setup(&diff_options);
|
||||
while (1 < argc && argv[1][0] == '-') {
|
||||
if (!strcmp(argv[1], "--")) {
|
||||
|
@ -180,7 +180,7 @@ int main(int argc, const char **argv)
|
||||
int allow_options = 1;
|
||||
int i;
|
||||
|
||||
git_config(git_default_config);
|
||||
git_config(git_diff_config);
|
||||
diff_setup(&diff_options);
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
@ -55,6 +55,9 @@ int main(int ac, const char **av)
|
||||
{
|
||||
int stage1, stage2;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
git_config(git_diff_config);
|
||||
read_cache();
|
||||
diff_setup(&diff_options);
|
||||
while (1 < ac && av[1][0] == '-') {
|
||||
|
64
diff-tree.c
64
diff-tree.c
@ -3,6 +3,7 @@
|
||||
#include "commit.h"
|
||||
|
||||
static int show_root_diff = 0;
|
||||
static int no_commit_id = 0;
|
||||
static int verbose_header = 0;
|
||||
static int ignore_merges = 1;
|
||||
static int read_stdin = 0;
|
||||
@ -29,7 +30,8 @@ static int call_diff_flush(void)
|
||||
return 0;
|
||||
}
|
||||
if (header) {
|
||||
printf("%s%c", header, diff_options.line_termination);
|
||||
if (!no_commit_id)
|
||||
printf("%s%c", header, diff_options.line_termination);
|
||||
header = NULL;
|
||||
}
|
||||
diff_flush(&diff_options);
|
||||
@ -67,52 +69,50 @@ static int diff_root_tree(const unsigned char *new, const char *base)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const char *generate_header(const char *commit, const char *parent, const char *msg, unsigned long len)
|
||||
static const char *generate_header(const char *commit, const char *parent, const char *msg)
|
||||
{
|
||||
static char this_header[16384];
|
||||
int offset;
|
||||
unsigned long len;
|
||||
|
||||
if (!verbose_header)
|
||||
return commit;
|
||||
|
||||
len = strlen(msg);
|
||||
offset = sprintf(this_header, "%s%s (from %s)\n", header_prefix, commit, parent);
|
||||
offset += pretty_print_commit(commit_format, msg, len, this_header + offset, sizeof(this_header) - offset);
|
||||
return this_header;
|
||||
}
|
||||
|
||||
static int diff_tree_commit(const unsigned char *commit, const char *name)
|
||||
static int diff_tree_commit(const unsigned char *commit_sha1)
|
||||
{
|
||||
unsigned long size, offset;
|
||||
char *buf = read_object_with_reference(commit, "commit", &size, NULL);
|
||||
struct commit *commit;
|
||||
struct commit_list *parents;
|
||||
char name[50];
|
||||
unsigned char sha1[20];
|
||||
|
||||
if (!buf)
|
||||
sprintf(name, "%s^0", sha1_to_hex(commit_sha1));
|
||||
if (get_sha1(name, sha1))
|
||||
return -1;
|
||||
|
||||
if (!name) {
|
||||
static char commit_name[60];
|
||||
strcpy(commit_name, sha1_to_hex(commit));
|
||||
name = commit_name;
|
||||
}
|
||||
|
||||
name[40] = 0;
|
||||
commit = lookup_commit(sha1);
|
||||
|
||||
/* Root commit? */
|
||||
if (show_root_diff && memcmp(buf + 46, "parent ", 7)) {
|
||||
header = generate_header(name, "root", buf, size);
|
||||
diff_root_tree(commit, "");
|
||||
if (show_root_diff && !commit->parents) {
|
||||
header = generate_header(name, "root", commit->buffer);
|
||||
diff_root_tree(commit_sha1, "");
|
||||
}
|
||||
|
||||
/* More than one parent? */
|
||||
if (ignore_merges) {
|
||||
if (!memcmp(buf + 46 + 48, "parent ", 7))
|
||||
if (ignore_merges && commit->parents && commit->parents->next)
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset = 46;
|
||||
while (offset + 48 < size && !memcmp(buf + offset, "parent ", 7)) {
|
||||
unsigned char parent[20];
|
||||
if (get_sha1_hex(buf + offset + 7, parent))
|
||||
return -1;
|
||||
header = generate_header(name, sha1_to_hex(parent), buf, size);
|
||||
diff_tree_sha1_top(parent, commit, "");
|
||||
for (parents = commit->parents; parents; parents = parents->next) {
|
||||
struct commit *parent = parents->item;
|
||||
header = generate_header(name,
|
||||
sha1_to_hex(parent->object.sha1),
|
||||
commit->buffer);
|
||||
diff_tree_sha1_top(parent->object.sha1, commit_sha1, "");
|
||||
if (!header && verbose_header) {
|
||||
header_prefix = "\ndiff-tree ";
|
||||
/*
|
||||
@ -120,9 +120,7 @@ static int diff_tree_commit(const unsigned char *commit, const char *name)
|
||||
* don't print the diffs.
|
||||
*/
|
||||
}
|
||||
offset += 48;
|
||||
}
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -145,7 +143,7 @@ static int diff_tree_stdin(char *line)
|
||||
return diff_tree_sha1_top(parent, commit, "");
|
||||
}
|
||||
line[40] = 0;
|
||||
return diff_tree_commit(commit, line);
|
||||
return diff_tree_commit(commit);
|
||||
}
|
||||
|
||||
static const char diff_tree_usage[] =
|
||||
@ -162,7 +160,7 @@ int main(int argc, const char **argv)
|
||||
unsigned char sha1[2][20];
|
||||
const char *prefix = setup_git_directory();
|
||||
|
||||
git_config(git_default_config);
|
||||
git_config(git_diff_config);
|
||||
nr_sha1 = 0;
|
||||
diff_setup(&diff_options);
|
||||
|
||||
@ -231,6 +229,10 @@ int main(int argc, const char **argv)
|
||||
show_root_diff = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--no-commit-id")) {
|
||||
no_commit_id = 1;
|
||||
continue;
|
||||
}
|
||||
usage(diff_tree_usage);
|
||||
}
|
||||
if (diff_options.output_format == DIFF_FORMAT_PATCH)
|
||||
@ -244,7 +246,7 @@ int main(int argc, const char **argv)
|
||||
usage(diff_tree_usage);
|
||||
break;
|
||||
case 1:
|
||||
diff_tree_commit(sha1[0], NULL);
|
||||
diff_tree_commit(sha1[0]);
|
||||
break;
|
||||
case 2:
|
||||
diff_tree_sha1_top(sha1[0], sha1[1], "");
|
||||
|
62
diff.c
62
diff.c
@ -13,6 +13,18 @@ static const char *diff_opts = "-pu";
|
||||
|
||||
static int use_size_cache;
|
||||
|
||||
int diff_rename_limit_default = -1;
|
||||
|
||||
int git_diff_config(const char *var, const char *value)
|
||||
{
|
||||
if (!strcmp(var, "diff.renamelimit")) {
|
||||
diff_rename_limit_default = git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_default_config(var, value);
|
||||
}
|
||||
|
||||
static char *quote_one(const char *str)
|
||||
{
|
||||
int needlen;
|
||||
@ -648,7 +660,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
|
||||
memset(one->sha1, 0, 20);
|
||||
}
|
||||
|
||||
static void run_diff(struct diff_filepair *p)
|
||||
static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
||||
{
|
||||
const char *pgm = external_diff();
|
||||
char msg[PATH_MAX*2+300], *xfrm_msg;
|
||||
@ -711,11 +723,11 @@ static void run_diff(struct diff_filepair *p)
|
||||
|
||||
if (memcmp(one->sha1, two->sha1, 20)) {
|
||||
char one_sha1[41];
|
||||
const char *index_fmt = o->full_index ? "index %s..%s" : "index %.7s..%.7s";
|
||||
memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
|
||||
|
||||
len += snprintf(msg + len, sizeof(msg) - len,
|
||||
"index %.7s..%.7s", one_sha1,
|
||||
sha1_to_hex(two->sha1));
|
||||
index_fmt, one_sha1, sha1_to_hex(two->sha1));
|
||||
if (one->mode == two->mode)
|
||||
len += snprintf(msg + len, sizeof(msg) - len,
|
||||
" %06o", one->mode);
|
||||
@ -761,9 +773,12 @@ void diff_setup(struct diff_options *options)
|
||||
|
||||
int diff_setup_done(struct diff_options *options)
|
||||
{
|
||||
if ((options->find_copies_harder || 0 <= options->rename_limit) &&
|
||||
options->detect_rename != DIFF_DETECT_COPY)
|
||||
if ((options->find_copies_harder &&
|
||||
options->detect_rename != DIFF_DETECT_COPY) ||
|
||||
(0 <= options->rename_limit && !options->detect_rename))
|
||||
return -1;
|
||||
if (options->detect_rename && options->rename_limit < 0)
|
||||
options->rename_limit = diff_rename_limit_default;
|
||||
if (options->setup & DIFF_SETUP_USE_CACHE) {
|
||||
if (!active_cache)
|
||||
/* read-cache does not die even when it fails
|
||||
@ -789,6 +804,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||
options->line_termination = 0;
|
||||
else if (!strncmp(arg, "-l", 2))
|
||||
options->rename_limit = strtoul(arg+2, NULL, 10);
|
||||
else if (!strcmp(arg, "--full-index"))
|
||||
options->full_index = 1;
|
||||
else if (!strcmp(arg, "--name-only"))
|
||||
options->output_format = DIFF_FORMAT_NAME;
|
||||
else if (!strcmp(arg, "--name-status"))
|
||||
@ -831,16 +848,29 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||
|
||||
static int parse_num(const char **cp_p)
|
||||
{
|
||||
int num, scale, ch, cnt;
|
||||
unsigned long num, scale;
|
||||
int ch, dot;
|
||||
const char *cp = *cp_p;
|
||||
|
||||
cnt = num = 0;
|
||||
num = 0;
|
||||
scale = 1;
|
||||
while ('0' <= (ch = *cp) && ch <= '9') {
|
||||
if (cnt++ < 5) {
|
||||
/* We simply ignore more than 5 digits precision. */
|
||||
scale *= 10;
|
||||
num = num * 10 + ch - '0';
|
||||
dot = 0;
|
||||
for(;;) {
|
||||
ch = *cp;
|
||||
if ( !dot && ch == '.' ) {
|
||||
scale = 1;
|
||||
dot = 1;
|
||||
} else if ( ch == '%' ) {
|
||||
scale = dot ? scale*100 : 100;
|
||||
cp++; /* % is always at the end */
|
||||
break;
|
||||
} else if ( ch >= '0' && ch <= '9' ) {
|
||||
if ( scale < 100000 ) {
|
||||
scale *= 10;
|
||||
num = (num*10) + (ch-'0');
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
@ -849,7 +879,7 @@ static int parse_num(const char **cp_p)
|
||||
/* user says num divided by scale and we say internally that
|
||||
* is MAX_SCORE * num / scale.
|
||||
*/
|
||||
return (MAX_SCORE * num / scale);
|
||||
return (num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale);
|
||||
}
|
||||
|
||||
int diff_scoreopt_parse(const char *opt)
|
||||
@ -1017,7 +1047,7 @@ int diff_unmodified_pair(struct diff_filepair *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void diff_flush_patch(struct diff_filepair *p)
|
||||
static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
|
||||
{
|
||||
if (diff_unmodified_pair(p))
|
||||
return;
|
||||
@ -1026,7 +1056,7 @@ static void diff_flush_patch(struct diff_filepair *p)
|
||||
(DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
|
||||
return; /* no tree diffs in patch format */
|
||||
|
||||
run_diff(p);
|
||||
run_diff(p, o);
|
||||
}
|
||||
|
||||
int diff_queue_is_empty(void)
|
||||
@ -1158,7 +1188,7 @@ void diff_flush(struct diff_options *options)
|
||||
die("internal error in diff-resolve-rename-copy");
|
||||
switch (diff_output_format) {
|
||||
case DIFF_FORMAT_PATCH:
|
||||
diff_flush_patch(p);
|
||||
diff_flush_patch(p, options);
|
||||
break;
|
||||
case DIFF_FORMAT_RAW:
|
||||
case DIFF_FORMAT_NAME_STATUS:
|
||||
|
5
diff.h
5
diff.h
@ -32,7 +32,8 @@ struct diff_options {
|
||||
const char *orderfile;
|
||||
const char *pickaxe;
|
||||
unsigned recursive:1,
|
||||
tree_in_recursive:1;
|
||||
tree_in_recursive:1,
|
||||
full_index:1;
|
||||
int break_opt;
|
||||
int detect_rename;
|
||||
int find_copies_harder;
|
||||
@ -76,6 +77,7 @@ extern int diff_scoreopt_parse(const char *opt);
|
||||
#define DIFF_SETUP_USE_CACHE 2
|
||||
#define DIFF_SETUP_USE_SIZE_CACHE 4
|
||||
|
||||
extern int git_diff_config(const char *var, const char *value);
|
||||
extern void diff_setup(struct diff_options *);
|
||||
extern int diff_opt_parse(struct diff_options *, const char **, int);
|
||||
extern int diff_setup_done(struct diff_options *);
|
||||
@ -96,6 +98,7 @@ extern void diffcore_std_no_resolve(struct diff_options *);
|
||||
" -u synonym for -p.\n" \
|
||||
" --name-only show only names of changed files.\n" \
|
||||
" --name-status show names and status of changed files.\n" \
|
||||
" --full-index show full object name on index ines.\n" \
|
||||
" -R swap input file pairs.\n" \
|
||||
" -B detect complete rewrites.\n" \
|
||||
" -M detect renames.\n" \
|
||||
|
@ -283,7 +283,7 @@ void diffcore_rename(struct diff_options *options)
|
||||
register_rename_src(p->one, 1);
|
||||
}
|
||||
if (rename_dst_nr == 0 ||
|
||||
(0 <= rename_limit && rename_limit < rename_dst_nr))
|
||||
(0 < rename_limit && rename_limit < rename_dst_nr))
|
||||
goto cleanup; /* nothing to do */
|
||||
|
||||
/* We really want to cull the candidates list early
|
||||
@ -307,6 +307,9 @@ void diffcore_rename(struct diff_options *options)
|
||||
if (rename_count == rename_dst_nr)
|
||||
goto cleanup;
|
||||
|
||||
if (minimum_score == MAX_SCORE)
|
||||
goto cleanup;
|
||||
|
||||
num_create = (rename_dst_nr - rename_count);
|
||||
num_src = rename_src_nr;
|
||||
mx = xmalloc(sizeof(*mx) * num_create * num_src);
|
||||
|
@ -12,6 +12,7 @@
|
||||
char git_default_email[MAX_GITNAME];
|
||||
char git_default_name[MAX_GITNAME];
|
||||
int trust_executable_bit = 1;
|
||||
int only_use_symrefs = 0;
|
||||
|
||||
static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
|
||||
*git_graft_file;
|
||||
|
14
fetch-pack.c
14
fetch-pack.c
@ -458,5 +458,19 @@ int main(int argc, char **argv)
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
finish_connect(pid);
|
||||
|
||||
if (!ret && nr_heads) {
|
||||
/* If the heads to pull were given, we should have
|
||||
* consumed all of them by matching the remote.
|
||||
* Otherwise, 'git-fetch remote no-such-ref' would
|
||||
* silently succeed without issuing an error.
|
||||
*/
|
||||
for (i = 0; i < nr_heads; i++)
|
||||
if (heads[i] && heads[i][0]) {
|
||||
error("no such remote ref %s", heads[i]);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ static void check_connectivity(void)
|
||||
/* Look up all the requirements, warn about missing objects.. */
|
||||
for (i = 0; i < nr_objs; i++) {
|
||||
struct object *obj = objs[i];
|
||||
struct object_list *refs;
|
||||
|
||||
if (!obj->parsed) {
|
||||
if (!standalone && has_sha1_file(obj->sha1))
|
||||
@ -67,14 +66,19 @@ static void check_connectivity(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
for (refs = obj->refs; refs; refs = refs->next) {
|
||||
if (refs->item->parsed ||
|
||||
(!standalone && has_sha1_file(refs->item->sha1)))
|
||||
continue;
|
||||
printf("broken link from %7s %s\n",
|
||||
obj->type, sha1_to_hex(obj->sha1));
|
||||
printf(" to %7s %s\n",
|
||||
refs->item->type, sha1_to_hex(refs->item->sha1));
|
||||
if (obj->refs) {
|
||||
const struct object_refs *refs = obj->refs;
|
||||
unsigned j;
|
||||
for (j = 0; j < refs->count; j++) {
|
||||
struct object *ref = refs->ref[j];
|
||||
if (ref->parsed ||
|
||||
(!standalone && has_sha1_file(ref->sha1)))
|
||||
continue;
|
||||
printf("broken link from %7s %s\n",
|
||||
obj->type, sha1_to_hex(obj->sha1));
|
||||
printf(" to %7s %s\n",
|
||||
ref->type, sha1_to_hex(ref->sha1));
|
||||
}
|
||||
}
|
||||
|
||||
if (show_unreachable && !(obj->flags & REACHABLE)) {
|
||||
@ -184,10 +188,17 @@ static int fsck_tree(struct tree *item)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(last->name);
|
||||
free(last);
|
||||
}
|
||||
|
||||
last = entry;
|
||||
}
|
||||
if (last) {
|
||||
free(last->name);
|
||||
free(last);
|
||||
}
|
||||
item->entries = NULL;
|
||||
|
||||
retval = 0;
|
||||
if (has_full_path) {
|
||||
|
112
git-am.sh
112
git-am.sh
@ -1,18 +1,12 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
#
|
||||
. git-sh-setup || die "Not a git archive"
|
||||
|
||||
files=$(git-diff-index --cached --name-only HEAD) || exit
|
||||
if [ "$files" ]; then
|
||||
echo "Dirty index: cannot apply patches (dirty: $files)" >&2
|
||||
exit 1
|
||||
fi
|
||||
. git-sh-setup
|
||||
|
||||
usage () {
|
||||
echo >&2 "usage: $0 [--signoff] [--dotest=<dir>] [--utf8] [--3way] <mbox>"
|
||||
echo >&2 "usage: $0 [--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way] <mbox>"
|
||||
echo >&2 " or, when resuming"
|
||||
echo >&2 " $0 [--skip]"
|
||||
echo >&2 " $0 [--skip | --resolved]"
|
||||
exit 1;
|
||||
}
|
||||
|
||||
@ -46,7 +40,7 @@ fall_back_3way () {
|
||||
cd "$dotest/patch-merge-tmp-dir" &&
|
||||
GIT_INDEX_FILE="../patch-merge-tmp-index" \
|
||||
GIT_OBJECT_DIRECTORY="$O_OBJECT" \
|
||||
git-apply --index <../patch
|
||||
git-apply $binary --index <../patch
|
||||
)
|
||||
then
|
||||
echo Using index info to reconstruct a base tree...
|
||||
@ -77,7 +71,7 @@ fall_back_3way () {
|
||||
GIT_OBJECT_DIRECTORY="$O_OBJECT" &&
|
||||
export GIT_INDEX_FILE GIT_OBJECT_DIRECTORY &&
|
||||
git-read-tree "$base" &&
|
||||
git-apply --index &&
|
||||
git-apply $binary --index &&
|
||||
mv ../patch-merge-tmp-index ../patch-merge-index &&
|
||||
echo "$base" >../patch-merge-base
|
||||
) <"$dotest/patch" 2>/dev/null && break
|
||||
@ -104,7 +98,7 @@ fall_back_3way () {
|
||||
}
|
||||
|
||||
prec=4
|
||||
dotest=.dotest sign= utf8= keep= skip= interactive=
|
||||
dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary=
|
||||
|
||||
while case "$#" in 0) break;; esac
|
||||
do
|
||||
@ -119,6 +113,9 @@ do
|
||||
--interacti|--interactiv|--interactive)
|
||||
interactive=t; shift ;;
|
||||
|
||||
-b|--b|--bi|--bin|--bina|--binar|--binary)
|
||||
binary=t; shift ;;
|
||||
|
||||
-3|--3|--3w|--3wa|--3way)
|
||||
threeway=t; shift ;;
|
||||
-s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
|
||||
@ -128,6 +125,9 @@ do
|
||||
-k|--k|--ke|--kee|--keep)
|
||||
keep=t; shift ;;
|
||||
|
||||
-r|--r|--re|--res|--reso|--resol|--resolv|--resolve|--resolved)
|
||||
resolved=t; shift ;;
|
||||
|
||||
--sk|--ski|--skip)
|
||||
skip=t; shift ;;
|
||||
|
||||
@ -140,6 +140,8 @@ do
|
||||
esac
|
||||
done
|
||||
|
||||
# If the dotest directory exists, but we have finished applying all the
|
||||
# patches in them, clear it out.
|
||||
if test -d "$dotest" &&
|
||||
last=$(cat "$dotest/last") &&
|
||||
next=$(cat "$dotest/next") &&
|
||||
@ -155,9 +157,9 @@ then
|
||||
die "previous dotest directory $dotest still exists but mbox given."
|
||||
resume=yes
|
||||
else
|
||||
# Make sure we are not given --skip
|
||||
test ",$skip," = ,, ||
|
||||
die "we are not resuming."
|
||||
# Make sure we are not given --skip nor --resolved
|
||||
test ",$skip,$resolved," = ,,, ||
|
||||
die "we are not resuming."
|
||||
|
||||
# Start afresh.
|
||||
mkdir -p "$dotest" || exit
|
||||
@ -170,12 +172,29 @@ else
|
||||
exit 1
|
||||
}
|
||||
|
||||
# -b, -s, -u and -k flags are kept for the resuming session after
|
||||
# a patch failure.
|
||||
# -3 and -i can and must be given when resuming.
|
||||
echo "$binary" >"$dotest/binary"
|
||||
echo "$sign" >"$dotest/sign"
|
||||
echo "$utf8" >"$dotest/utf8"
|
||||
echo "$keep" >"$dotest/keep"
|
||||
echo 1 >"$dotest/next"
|
||||
fi
|
||||
|
||||
case "$resolved" in
|
||||
'')
|
||||
files=$(git-diff-index --cached --name-only HEAD) || exit
|
||||
if [ "$files" ]; then
|
||||
echo "Dirty index: cannot apply patches (dirty: $files)" >&2
|
||||
exit 1
|
||||
fi
|
||||
esac
|
||||
|
||||
if test "$(cat "$dotest/binary")" = t
|
||||
then
|
||||
binary=--allow-binary-replacement
|
||||
fi
|
||||
if test "$(cat "$dotest/utf8")" = t
|
||||
then
|
||||
utf8=-u
|
||||
@ -216,6 +235,15 @@ do
|
||||
go_next
|
||||
continue
|
||||
}
|
||||
|
||||
# If we are not resuming, parse and extract the patch information
|
||||
# into separate files:
|
||||
# - info records the authorship and title
|
||||
# - msg is the rest of commit log message
|
||||
# - patch is the patch body.
|
||||
#
|
||||
# When we are resuming, these files are either already prepared
|
||||
# by the user, or the user can tell us to do so by --resolved flag.
|
||||
case "$resume" in
|
||||
'')
|
||||
git-mailinfo $keep $utf8 "$dotest/msg" "$dotest/patch" \
|
||||
@ -224,29 +252,33 @@ do
|
||||
git-stripspace < "$dotest/msg" > "$dotest/msg-clean"
|
||||
;;
|
||||
esac
|
||||
resume=
|
||||
|
||||
GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$dotest/info")"
|
||||
GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$dotest/info")"
|
||||
GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$dotest/info")"
|
||||
SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$dotest/info")"
|
||||
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
|
||||
|
||||
SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$dotest/info")"
|
||||
case "$keep_subject" in -k) SUBJECT="[PATCH] $SUBJECT" ;; esac
|
||||
if test '' != "$SIGNOFF"
|
||||
then
|
||||
|
||||
case "$resume" in
|
||||
'')
|
||||
if test '' != "$SIGNOFF"
|
||||
then
|
||||
LAST_SIGNED_OFF_BY=`
|
||||
sed -ne '/^Signed-off-by: /p' "$dotest/msg-clean" |
|
||||
tail -n 1
|
||||
sed -ne '/^Signed-off-by: /p' \
|
||||
"$dotest/msg-clean" |
|
||||
tail -n 1
|
||||
`
|
||||
ADD_SIGNOFF=$(test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || {
|
||||
ADD_SIGNOFF=`
|
||||
test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || {
|
||||
test '' = "$LAST_SIGNED_OFF_BY" && echo
|
||||
echo "$SIGNOFF"
|
||||
})
|
||||
else
|
||||
}`
|
||||
else
|
||||
ADD_SIGNOFF=
|
||||
fi
|
||||
{
|
||||
fi
|
||||
{
|
||||
echo "$SUBJECT"
|
||||
if test -s "$dotest/msg-clean"
|
||||
then
|
||||
@ -257,8 +289,18 @@ do
|
||||
then
|
||||
echo "$ADD_SIGNOFF"
|
||||
fi
|
||||
} >"$dotest/final-commit"
|
||||
} >"$dotest/final-commit"
|
||||
;;
|
||||
*)
|
||||
case "$resolved,$interactive" in
|
||||
tt)
|
||||
# This is used only for interactive view option.
|
||||
git-diff-index -p --cached HEAD >"$dotest/patch"
|
||||
;;
|
||||
esac
|
||||
esac
|
||||
|
||||
resume=
|
||||
if test "$interactive" = t
|
||||
then
|
||||
test -t 0 ||
|
||||
@ -303,7 +345,21 @@ do
|
||||
echo "Applying '$SUBJECT'"
|
||||
echo
|
||||
|
||||
git-apply --index "$dotest/patch"; apply_status=$?
|
||||
case "$resolved" in
|
||||
'')
|
||||
git-apply $binary --index "$dotest/patch"
|
||||
apply_status=$?
|
||||
;;
|
||||
t)
|
||||
# Resolved means the user did all the hard work, and
|
||||
# we do not have to do any patch application. Just
|
||||
# trust what the user has in the index file and the
|
||||
# working tree.
|
||||
resolved=
|
||||
apply_status=0
|
||||
;;
|
||||
esac
|
||||
|
||||
if test $apply_status = 1 && test "$threeway" = t
|
||||
then
|
||||
if (fall_back_3way)
|
||||
|
@ -18,7 +18,7 @@
|
||||
##
|
||||
## git-am is supposed to be the newer and better tool for this job.
|
||||
|
||||
. git-sh-setup || die "Not a git archive"
|
||||
. git-sh-setup
|
||||
|
||||
usage () {
|
||||
echo >&2 "applymbox [-u] [-k] [-q] [-m] (-c .dotest/<num> | mbox) [signoff]"
|
||||
|
@ -10,7 +10,7 @@
|
||||
## $3 - "info" file with Author, email and subject
|
||||
## $4 - optional file containing signoff to add
|
||||
##
|
||||
. git-sh-setup || die "Not a git archive."
|
||||
. git-sh-setup
|
||||
|
||||
final=.dotest/final-commit
|
||||
##
|
||||
|
@ -30,6 +30,24 @@ See man (1) git-archimport for more details.
|
||||
|
||||
Add print in front of the shell commands invoked via backticks.
|
||||
|
||||
=head1 Devel Notes
|
||||
|
||||
There are several places where Arch and git terminology are intermixed
|
||||
and potentially confused.
|
||||
|
||||
The notion of a "branch" in git is approximately equivalent to
|
||||
a "archive/category--branch--version" in Arch. Also, it should be noted
|
||||
that the "--branch" portion of "archive/category--branch--version" is really
|
||||
optional in Arch although not many people (nor tools!) seem to know this.
|
||||
This means that "archive/category--version" is also a valid "branch"
|
||||
in git terms.
|
||||
|
||||
We always refer to Arch names by their fully qualified variant (which
|
||||
means the "archive" name is prefixed.
|
||||
|
||||
For people unfamiliar with Arch, an "archive" is the term for "repository",
|
||||
and can contain multiple, unrelated branches.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
@ -52,14 +70,14 @@ $ENV{'TZ'}="UTC";
|
||||
|
||||
my $git_dir = $ENV{"GIT_DIR"} || ".git";
|
||||
$ENV{"GIT_DIR"} = $git_dir;
|
||||
my $ptag_dir = "$git_dir/archimport/tags";
|
||||
|
||||
our($opt_h,$opt_v, $opt_T,
|
||||
$opt_C,$opt_t);
|
||||
our($opt_h,$opt_v, $opt_T,$opt_t,$opt_o);
|
||||
|
||||
sub usage() {
|
||||
print STDERR <<END;
|
||||
Usage: ${\basename $0} # fetch/update GIT from Arch
|
||||
[ -h ] [ -v ] [ -T ] [ -t tempdir ]
|
||||
[ -o ] [ -h ] [ -v ] [ -T ] [ -t tempdir ]
|
||||
repository/arch-branch [ repository/arch-branch] ...
|
||||
END
|
||||
exit(1);
|
||||
@ -195,25 +213,68 @@ unless (-d $git_dir) { # initial import
|
||||
opendir(DIR, "$git_dir/archimport/tags")
|
||||
|| die "can't opendir: $!";
|
||||
while (my $file = readdir(DIR)) {
|
||||
# skip non-interesting-files
|
||||
next unless -f "$git_dir/archimport/tags/$file";
|
||||
next if $file =~ m/--base-0$/; # don't care for base-0
|
||||
# skip non-interesting-files
|
||||
next unless -f "$ptag_dir/$file";
|
||||
|
||||
# convert first '--' to '/' from old git-archimport to use
|
||||
# as an archivename/c--b--v private tag
|
||||
if ($file !~ m!,!) {
|
||||
my $oldfile = $file;
|
||||
$file =~ s!--!,!;
|
||||
print STDERR "converting old tag $oldfile to $file\n";
|
||||
rename("$ptag_dir/$oldfile", "$ptag_dir/$file") or die $!;
|
||||
}
|
||||
my $sha = ptag($file);
|
||||
chomp $sha;
|
||||
# reconvert the 3rd '--' sequence from the end
|
||||
# into a slash
|
||||
# $file = reverse $file;
|
||||
# $file =~ s!^(.+?--.+?--.+?--.+?)--(.+)$!$1/$2!;
|
||||
# $file = reverse $file;
|
||||
$rptags{$sha} = $file;
|
||||
}
|
||||
closedir DIR;
|
||||
}
|
||||
|
||||
# process patchsets
|
||||
foreach my $ps (@psets) {
|
||||
# extract the Arch repository name (Arch "archive" in Arch-speak)
|
||||
sub extract_reponame {
|
||||
my $fq_cvbr = shift; # archivename/[[[[category]branch]version]revision]
|
||||
return (split(/\//, $fq_cvbr))[0];
|
||||
}
|
||||
|
||||
sub extract_versionname {
|
||||
my $name = shift;
|
||||
$name =~ s/--(?:patch|version(?:fix)?|base)-\d+$//;
|
||||
return $name;
|
||||
}
|
||||
|
||||
$ps->{branch} = branchname($ps->{id});
|
||||
# convert a fully-qualified revision or version to a unique dirname:
|
||||
# normalperson@yhbt.net-05/mpd--uclinux--1--patch-2
|
||||
# becomes: normalperson@yhbt.net-05,mpd--uclinux--1
|
||||
#
|
||||
# the git notion of a branch is closer to
|
||||
# archive/category--branch--version than archive/category--branch, so we
|
||||
# use this to convert to git branch names.
|
||||
# Also, keep archive names but replace '/' with ',' since it won't require
|
||||
# subdirectories, and is safer than swapping '--' which could confuse
|
||||
# reverse-mapping when dealing with bastard branches that
|
||||
# are just archive/category--version (no --branch)
|
||||
sub tree_dirname {
|
||||
my $revision = shift;
|
||||
my $name = extract_versionname($revision);
|
||||
$name =~ s#/#,#;
|
||||
return $name;
|
||||
}
|
||||
|
||||
# old versions of git-archimport just use the <category--branch> part:
|
||||
sub old_style_branchname {
|
||||
my $id = shift;
|
||||
my $ret = safe_pipe_capture($TLA,'parse-package-name','-p',$id);
|
||||
chomp $ret;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
*git_branchname = $opt_o ? *old_style_branchname : *tree_dirname;
|
||||
|
||||
# process patchsets
|
||||
foreach my $ps (@psets) {
|
||||
$ps->{branch} = git_branchname($ps->{id});
|
||||
|
||||
#
|
||||
# ensure we have a clean state
|
||||
@ -410,8 +471,7 @@ foreach my $ps (@psets) {
|
||||
open HEAD, ">$git_dir/refs/heads/$ps->{branch}";
|
||||
print HEAD $commitid;
|
||||
close HEAD;
|
||||
unlink ("$git_dir/HEAD");
|
||||
symlink("refs/heads/$ps->{branch}","$git_dir/HEAD");
|
||||
system('git-update-ref', 'HEAD', "$ps->{branch}");
|
||||
|
||||
# tag accordingly
|
||||
ptag($ps->{id}, $commitid); # private tag
|
||||
@ -425,16 +485,9 @@ foreach my $ps (@psets) {
|
||||
$opt_v && print " + parents: $par \n";
|
||||
}
|
||||
|
||||
sub branchname {
|
||||
my $id = shift;
|
||||
$id =~ s#^.+?/##;
|
||||
my @parts = split(m/--/, $id);
|
||||
return join('--', @parts[0..1]);
|
||||
}
|
||||
|
||||
sub apply_import {
|
||||
my $ps = shift;
|
||||
my $bname = branchname($ps->{id});
|
||||
my $bname = git_branchname($ps->{id});
|
||||
|
||||
`mkdir -p $tmp`;
|
||||
|
||||
@ -565,6 +618,11 @@ sub parselog {
|
||||
next if $t =~ m!\{arch\}/!;
|
||||
next if $t =~ m!\.arch-ids/!;
|
||||
next if $t =~ m!\.arch-inventory$!;
|
||||
# tla cat-archive-log will give us filenames with spaces as file\(sp)name - why?
|
||||
# we can assume that any filename with \ indicates some pika escaping that we want to get rid of.
|
||||
if ($t =~ /\\/ ){
|
||||
$t = `tla escape --unescaped '$t'`;
|
||||
}
|
||||
push (@tmp, shell_quote($t));
|
||||
}
|
||||
@$ref = @tmp;
|
||||
@ -577,19 +635,24 @@ sub parselog {
|
||||
# write/read a tag
|
||||
sub tag {
|
||||
my ($tag, $commit) = @_;
|
||||
$tag =~ s|/|--|g;
|
||||
$tag = shell_quote($tag);
|
||||
|
||||
if ($opt_o) {
|
||||
$tag =~ s|/|--|g;
|
||||
} else {
|
||||
# don't use subdirs for tags yet, it could screw up other porcelains
|
||||
$tag =~ s|/|,|g;
|
||||
}
|
||||
|
||||
if ($commit) {
|
||||
open(C,">$git_dir/refs/tags/$tag")
|
||||
open(C,">","$git_dir/refs/tags/$tag")
|
||||
or die "Cannot create tag $tag: $!\n";
|
||||
print C "$commit\n"
|
||||
or die "Cannot write tag $tag: $!\n";
|
||||
close(C)
|
||||
or die "Cannot write tag $tag: $!\n";
|
||||
print " * Created tag ' $tag' on '$commit'\n" if $opt_v;
|
||||
print " * Created tag '$tag' on '$commit'\n" if $opt_v;
|
||||
} else { # read
|
||||
open(C,"<$git_dir/refs/tags/$tag")
|
||||
open(C,"<","$git_dir/refs/tags/$tag")
|
||||
or die "Cannot read tag $tag: $!\n";
|
||||
$commit = <C>;
|
||||
chomp $commit;
|
||||
@ -604,15 +667,16 @@ sub tag {
|
||||
# reads fail softly if the tag isn't there
|
||||
sub ptag {
|
||||
my ($tag, $commit) = @_;
|
||||
$tag =~ s|/|--|g;
|
||||
$tag = shell_quote($tag);
|
||||
|
||||
# don't use subdirs for tags yet, it could screw up other porcelains
|
||||
$tag =~ s|/|,|g;
|
||||
|
||||
unless (-d "$git_dir/archimport/tags") {
|
||||
mkpath("$git_dir/archimport/tags");
|
||||
}
|
||||
my $tag_file = "$ptag_dir/$tag";
|
||||
my $tag_branch_dir = dirname($tag_file);
|
||||
mkpath($tag_branch_dir) unless (-d $tag_branch_dir);
|
||||
|
||||
if ($commit) { # write
|
||||
open(C,">$git_dir/archimport/tags/$tag")
|
||||
open(C,">",$tag_file)
|
||||
or die "Cannot create tag $tag: $!\n";
|
||||
print C "$commit\n"
|
||||
or die "Cannot write tag $tag: $!\n";
|
||||
@ -622,10 +686,10 @@ sub ptag {
|
||||
unless $tag =~ m/--base-0$/;
|
||||
} else { # read
|
||||
# if the tag isn't there, return 0
|
||||
unless ( -s "$git_dir/archimport/tags/$tag") {
|
||||
unless ( -s $tag_file) {
|
||||
return 0;
|
||||
}
|
||||
open(C,"<$git_dir/archimport/tags/$tag")
|
||||
open(C,"<",$tag_file)
|
||||
or die "Cannot read tag $tag: $!\n";
|
||||
$commit = <C>;
|
||||
chomp $commit;
|
||||
@ -658,7 +722,7 @@ sub find_parents {
|
||||
# simple loop to split the merges
|
||||
# per branch
|
||||
foreach my $merge (@{$ps->{merges}}) {
|
||||
my $branch = branchname($merge);
|
||||
my $branch = git_branchname($merge);
|
||||
unless (defined $branches{$branch} ){
|
||||
$branches{$branch} = [];
|
||||
}
|
||||
@ -682,7 +746,13 @@ sub find_parents {
|
||||
next unless -e "$git_dir/refs/heads/$branch";
|
||||
|
||||
my $mergebase = `git-merge-base $branch $ps->{branch}`;
|
||||
die "Cannot find merge base for $branch and $ps->{branch}" if $?;
|
||||
if ($?) {
|
||||
# Don't die here, Arch supports one-way cherry-picking
|
||||
# between branches with no common base (or any relationship
|
||||
# at all beforehand)
|
||||
warn "Cannot find merge base for $branch and $ps->{branch}";
|
||||
next;
|
||||
}
|
||||
chomp $mergebase;
|
||||
|
||||
# now walk up to the mergepoint collecting what patches we have
|
||||
@ -775,12 +845,7 @@ sub commitid2pset {
|
||||
chomp $commitid;
|
||||
my $name = $rptags{$commitid}
|
||||
|| die "Cannot find reverse tag mapping for $commitid";
|
||||
# the keys in %rptag are slightly munged; unmunge
|
||||
# reconvert the 3rd '--' sequence from the end
|
||||
# into a slash
|
||||
$name = reverse $name;
|
||||
$name =~ s!^(.+?--.+?--.+?--.+?)--(.+)$!$1/$2!;
|
||||
$name = reverse $name;
|
||||
$name =~ s|,|/|;
|
||||
my $ps = $psets{$name}
|
||||
|| (print Dumper(sort keys %psets)) && die "Cannot find patchset for $name";
|
||||
return $ps;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
. git-sh-setup || dir "Not a git archive"
|
||||
. git-sh-setup
|
||||
|
||||
usage() {
|
||||
echo >&2 'usage: git bisect [start|bad|good|next|reset|visualize]
|
||||
|
@ -1,9 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
. git-sh-setup || die "Not a git archive"
|
||||
. git-sh-setup
|
||||
|
||||
usage () {
|
||||
echo >&2 "usage: $(basename $0)"' [-d <branch>] | [<branch> [start-point]]
|
||||
echo >&2 "usage: $(basename $0)"' [-d <branch>] | [[-f] <branch> [start-point]]
|
||||
|
||||
If no arguments, show available branches and mark current branch with a star.
|
||||
If one argument, create a new branch <branchname> based off of current HEAD.
|
||||
@ -12,11 +12,12 @@ If two arguments, create a new branch <branchname> based off of <start-point>.
|
||||
exit 1
|
||||
}
|
||||
|
||||
headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD |
|
||||
sed -e 's|^refs/heads/||')
|
||||
|
||||
delete_branch () {
|
||||
option="$1"
|
||||
shift
|
||||
headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD |
|
||||
sed -e 's|^refs/heads/||')
|
||||
for branch_name
|
||||
do
|
||||
case ",$headref," in
|
||||
@ -52,6 +53,7 @@ delete_branch () {
|
||||
exit 0
|
||||
}
|
||||
|
||||
force=
|
||||
while case "$#,$1" in 0,*) break ;; *,-*) ;; *) break ;; esac
|
||||
do
|
||||
case "$1" in
|
||||
@ -59,6 +61,9 @@ do
|
||||
delete_branch "$@"
|
||||
exit
|
||||
;;
|
||||
-f)
|
||||
force="$1"
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
@ -72,8 +77,6 @@ done
|
||||
|
||||
case "$#" in
|
||||
0)
|
||||
headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD |
|
||||
sed -e 's|^refs/heads/||')
|
||||
git-rev-parse --symbolic --all |
|
||||
sed -ne 's|^refs/heads/||p' |
|
||||
sort |
|
||||
@ -97,11 +100,18 @@ branchname="$1"
|
||||
|
||||
rev=$(git-rev-parse --verify "$head") || exit
|
||||
|
||||
[ -e "$GIT_DIR/refs/heads/$branchname" ] &&
|
||||
die "$branchname already exists."
|
||||
git-check-ref-format "heads/$branchname" ||
|
||||
die "we do not like '$branchname' as a branch name."
|
||||
|
||||
leading=`expr "refs/heads/$branchname" : '\(.*\)/'` &&
|
||||
mkdir -p "$GIT_DIR/$leading" &&
|
||||
echo $rev > "$GIT_DIR/refs/heads/$branchname"
|
||||
if [ -e "$GIT_DIR/refs/heads/$branchname" ]
|
||||
then
|
||||
if test '' = "$force"
|
||||
then
|
||||
die "$branchname already exists."
|
||||
elif test "$branchname" = "$headref"
|
||||
then
|
||||
die "cannot force-update the current branch."
|
||||
fi
|
||||
fi
|
||||
git update-ref "refs/heads/$branchname" $rev
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
. git-sh-setup || die "Not a git archive"
|
||||
. git-sh-setup
|
||||
|
||||
usage () {
|
||||
die "usage: git checkout [-f] [-b <new_branch>] [<branch>] [<paths>...]"
|
||||
@ -82,7 +82,6 @@ then
|
||||
# rescuing paths and is never meant to remove what
|
||||
# is not in the named tree-ish.
|
||||
git-ls-tree -r "$new" "$@" |
|
||||
sed -ne 's/^\([0-7]*\) blob \(.*\)$/\1 \2/p' |
|
||||
git-update-index --index-info || exit $?
|
||||
fi
|
||||
git-checkout-index -f -u -- "$@"
|
||||
|
@ -3,7 +3,7 @@
|
||||
# Copyright (c) 2005 Junio C Hamano.
|
||||
#
|
||||
|
||||
. git-sh-setup || die "Not a git archive."
|
||||
. git-sh-setup
|
||||
|
||||
usage="usage: $0 "'[-v] <upstream> [<head>]
|
||||
|
||||
|
25
git-clone.sh
25
git-clone.sh
@ -9,7 +9,7 @@
|
||||
unset CDPATH
|
||||
|
||||
usage() {
|
||||
echo >&2 "* git clone [-l [-s]] [-q] [-u <upload-pack>] [-n] <repo> <dir>"
|
||||
echo >&2 "* git clone [-l [-s]] [-q] [-u <upload-pack>] [-n] <repo> [<dir>]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ fi
|
||||
|
||||
http_fetch () {
|
||||
# $1 = Remote, $2 = Local
|
||||
curl -nsf $curl_extra_args "$1" >"$2"
|
||||
curl -nsfL $curl_extra_args "$1" >"$2"
|
||||
}
|
||||
|
||||
clone_dumb_http () {
|
||||
@ -96,7 +96,10 @@ if base=$(get_repo_base "$repo"); then
|
||||
fi
|
||||
|
||||
dir="$2"
|
||||
mkdir "$dir" &&
|
||||
# Try using "humanish" part of source repo if user didn't specify one
|
||||
[ -z "$dir" ] && dir=$(echo "$repo" | sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*/||g')
|
||||
[ -e "$dir" ] && echo "$dir already exists." && usage
|
||||
mkdir -p "$dir" &&
|
||||
D=$(
|
||||
(cd "$dir" && git-init-db && pwd)
|
||||
) &&
|
||||
@ -163,7 +166,7 @@ yes,yes)
|
||||
rm -f "$D/.git/TMP_ALT"
|
||||
if test -f "$D/.git/TMP_ALT"
|
||||
then
|
||||
( cd $D &&
|
||||
( cd "$D" &&
|
||||
. git-parse-remote &&
|
||||
resolve_alternates "$repo" <"./.git/TMP_ALT" ) |
|
||||
while read alt
|
||||
@ -191,7 +194,7 @@ yes,yes)
|
||||
;;
|
||||
esac
|
||||
|
||||
cd $D || exit
|
||||
cd "$D" || exit
|
||||
|
||||
if test -f ".git/HEAD"
|
||||
then
|
||||
@ -202,8 +205,16 @@ then
|
||||
mkdir -p .git/remotes &&
|
||||
echo >.git/remotes/origin \
|
||||
"URL: $repo
|
||||
Pull: $head_points_at:origin"
|
||||
cp ".git/refs/heads/$head_points_at" .git/refs/heads/origin
|
||||
Pull: $head_points_at:origin" &&
|
||||
cp ".git/refs/heads/$head_points_at" .git/refs/heads/origin &&
|
||||
find .git/refs/heads -type f -print |
|
||||
while read ref
|
||||
do
|
||||
head=`expr "$ref" : '.git/refs/heads/\(.*\)'` &&
|
||||
test "$head_points_at" = "$head" ||
|
||||
test "origin" = "$head" ||
|
||||
echo "Pull: ${head}:${head}"
|
||||
done >>.git/remotes/origin
|
||||
esac
|
||||
|
||||
case "$no_checkout" in
|
||||
|
@ -3,7 +3,7 @@
|
||||
# Copyright (c) 2005 Linus Torvalds
|
||||
#
|
||||
|
||||
. git-sh-setup || die "Not a git archive"
|
||||
. git-sh-setup
|
||||
|
||||
usage () {
|
||||
die 'git commit [-a] [-s] [-v | --no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit>] [-e] [<path>...]'
|
||||
@ -92,10 +92,13 @@ tt*)
|
||||
esac
|
||||
|
||||
case "$all,$#" in
|
||||
t,*)
|
||||
t,0)
|
||||
git-diff-files --name-only -z |
|
||||
git-update-index --remove -z --stdin
|
||||
;;
|
||||
t,*)
|
||||
die "Cannot use -a and explicit files at the same time."
|
||||
;;
|
||||
,0)
|
||||
;;
|
||||
*)
|
||||
@ -184,7 +187,7 @@ then
|
||||
}
|
||||
'
|
||||
set_author_env=`git-cat-file commit "$use_commit" |
|
||||
sed -ne "$pick_author_script"`
|
||||
LANG=C LC_ALL=C sed -ne "$pick_author_script"`
|
||||
eval "$set_author_env"
|
||||
export GIT_AUTHOR_NAME
|
||||
export GIT_AUTHOR_EMAIL
|
||||
|
@ -1,83 +0,0 @@
|
||||
# Pass --without docs to rpmbuild if you don't want the documetnation
|
||||
Name: git-core
|
||||
Version: @@VERSION@@
|
||||
Release: 1%{?dist}
|
||||
Summary: Git core and tools
|
||||
License: GPL
|
||||
Group: Development/Tools
|
||||
URL: http://kernel.org/pub/software/scm/git/
|
||||
Source: http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz
|
||||
BuildRequires: zlib-devel, openssl-devel, curl-devel %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
Requires: zlib >= 1.2, rsync, rcs, curl, less, openssh-clients, python >= 2.3, tk >= 8.4
|
||||
|
||||
%description
|
||||
This is a stupid (but extremely fast) directory content manager. It
|
||||
doesn't do a whole lot, but what it _does_ do is track directory
|
||||
contents efficiently. It is intended to be the base of an efficient,
|
||||
distributed source code management system. This package includes
|
||||
rudimentary tools that can be used as a SCM, but you should look
|
||||
elsewhere for tools for ordinary humans layered on top of this.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_OWN_SUBPROCESS_PY=YesPlease \
|
||||
prefix=%{_prefix} all %{!?_without_docs: doc}
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make %{_smp_mflags} DESTDIR=$RPM_BUILD_ROOT WITH_OWN_SUBPROCESS_PY=YesPlease \
|
||||
prefix=%{_prefix} mandir=%{_mandir} \
|
||||
install %{!?_without_docs: install-doc}
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%{_bindir}/*
|
||||
%{_datadir}/git-core/
|
||||
%doc README COPYING Documentation/*.txt
|
||||
%{!?_without_docs: %doc Documentation/*.html }
|
||||
%{!?_without_docs: %{_mandir}/man1/*.1*}
|
||||
%{!?_without_docs: %{_mandir}/man7/*.7*}
|
||||
|
||||
%changelog
|
||||
* Tue Sep 27 2005 H. Peter Anvin <hpa@zytor.com>
|
||||
- parallelize build
|
||||
- COPTS -> CFLAGS
|
||||
|
||||
* Fri Sep 16 2005 Chris Wright <chrisw@osdl.org> 0.99.6-1
|
||||
- update to 0.99.6
|
||||
|
||||
* Fri Sep 16 2005 Horst H. von Brand <vonbrand@inf.utfsm.cl>
|
||||
- Linus noticed that less is required, added to the dependencies
|
||||
|
||||
* Sun Sep 11 2005 Horst H. von Brand <vonbrand@inf.utfsm.cl>
|
||||
- Updated dependencies
|
||||
- Don't assume manpages are gzipped
|
||||
|
||||
* Thu Aug 18 2005 Chris Wright <chrisw@osdl.org> 0.99.4-4
|
||||
- drop sh_utils, sh-utils, diffutils, mktemp, and openssl Requires
|
||||
- use RPM_OPT_FLAGS in spec file, drop patch0
|
||||
|
||||
* Wed Aug 17 2005 Tom "spot" Callaway <tcallawa@redhat.com> 0.99.4-3
|
||||
- use dist tag to differentiate between branches
|
||||
- use rpm optflags by default (patch0)
|
||||
- own %{_datadir}/git-core/
|
||||
|
||||
* Mon Aug 15 2005 Chris Wright <chrisw@osdl.org>
|
||||
- update spec file to fix Buildroot, Requires, and drop Vendor
|
||||
|
||||
* Sun Aug 07 2005 Horst H. von Brand <vonbrand@inf.utfsm.cl>
|
||||
- Redid the description
|
||||
- Cut overlong make line, loosened changelog a bit
|
||||
- I think Junio (or perhaps OSDL?) should be vendor...
|
||||
|
||||
* Thu Jul 14 2005 Eric Biederman <ebiederm@xmission.com>
|
||||
- Add the man pages, and the --without docs build option
|
||||
|
||||
* Wed Jul 7 2005 Chris Wright <chris@osdl.org>
|
||||
- initial git spec file
|
@ -1,7 +1,25 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2005 Junio C Hamano
|
||||
#
|
||||
|
||||
. git-sh-setup
|
||||
|
||||
dc </dev/null 2>/dev/null || {
|
||||
# This is not a real DC at all -- it just knows how
|
||||
# this script feeds DC and does the computation itself.
|
||||
dc () {
|
||||
while read a b
|
||||
do
|
||||
case $a,$b in
|
||||
0,) acc=0 ;;
|
||||
*,+) acc=$(($acc + $a)) ;;
|
||||
p,) echo "$acc" ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
echo $(find "$GIT_DIR/objects"/?? -type f -print 2>/dev/null | wc -l) objects, \
|
||||
$({
|
||||
echo 0
|
||||
|
225
git-cvsexportcommit.perl
Executable file
225
git-cvsexportcommit.perl
Executable file
@ -0,0 +1,225 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use Getopt::Std;
|
||||
use File::Temp qw(tempdir);
|
||||
use Data::Dumper;
|
||||
use File::Basename qw(basename);
|
||||
|
||||
unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){
|
||||
die "GIT_DIR is not defined or is unreadable";
|
||||
}
|
||||
|
||||
our ($opt_h, $opt_p, $opt_v, $opt_c );
|
||||
|
||||
getopts('hpvc');
|
||||
|
||||
$opt_h && usage();
|
||||
|
||||
die "Need at least one commit identifier!" unless @ARGV;
|
||||
|
||||
# setup a tempdir
|
||||
our ($tmpdir, $tmpdirname) = tempdir('git-cvsapplycommit-XXXXXX',
|
||||
TMPDIR => 1,
|
||||
CLEANUP => 1);
|
||||
|
||||
print Dumper(@ARGV);
|
||||
# resolve target commit
|
||||
my $commit;
|
||||
$commit = pop @ARGV;
|
||||
$commit = `git-rev-parse --verify "$commit"^0`;
|
||||
chomp $commit;
|
||||
if ($?) {
|
||||
die "The commit reference $commit did not resolve!";
|
||||
}
|
||||
|
||||
# resolve what parent we want
|
||||
my $parent;
|
||||
if (@ARGV) {
|
||||
$parent = pop @ARGV;
|
||||
$parent = `git-rev-parse --verify "$parent"^0"`;
|
||||
chomp $parent;
|
||||
if ($?) {
|
||||
die "The parent reference did not resolve!";
|
||||
}
|
||||
}
|
||||
|
||||
# find parents from the commit itself
|
||||
my @commit = `git-cat-file commit $commit`;
|
||||
my @parents;
|
||||
foreach my $p (@commit) {
|
||||
if ($p =~ m/^$/) { # end of commit headers, we're done
|
||||
last;
|
||||
}
|
||||
if ($p =~ m/^parent (\w{40})$/) { # found a parent
|
||||
push @parents, $1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($parent) {
|
||||
# double check that it's a valid parent
|
||||
foreach my $p (@parents) {
|
||||
my $found;
|
||||
if ($p eq $parent) {
|
||||
$found = 1;
|
||||
last;
|
||||
}; # found it
|
||||
die "Did not find $parent in the parents for this commit!";
|
||||
}
|
||||
} else { # we don't have a parent from the cmdline...
|
||||
if (@parents == 1) { # it's safe to get it from the commit
|
||||
$parent = $parents[0];
|
||||
} else { # or perhaps not!
|
||||
die "This commit has more than one parent -- please name the parent you want to use explicitly";
|
||||
}
|
||||
}
|
||||
|
||||
$opt_v && print "Applying to CVS commit $commit from parent $parent\n";
|
||||
|
||||
# grab the commit message
|
||||
`git-cat-file commit $commit | sed -e '1,/^\$/d' > .msg`;
|
||||
$? && die "Error extracting the commit message";
|
||||
|
||||
my (@afiles, @dfiles, @mfiles);
|
||||
my @files = `git-diff-tree -r $parent $commit`;
|
||||
print @files;
|
||||
$? && die "Error in git-diff-tree";
|
||||
foreach my $f (@files) {
|
||||
chomp $f;
|
||||
my @fields = split(m/\s+/, $f);
|
||||
if ($fields[4] eq 'A') {
|
||||
push @afiles, $fields[5];
|
||||
}
|
||||
if ($fields[4] eq 'M') {
|
||||
push @mfiles, $fields[5];
|
||||
}
|
||||
if ($fields[4] eq 'R') {
|
||||
push @dfiles, $fields[5];
|
||||
}
|
||||
}
|
||||
$opt_v && print "The commit affects:\n ";
|
||||
$opt_v && print join ("\n ", @afiles,@mfiles,@dfiles) . "\n\n";
|
||||
undef @files; # don't need it anymore
|
||||
|
||||
# check that the files are clean and up to date according to cvs
|
||||
my $dirty;
|
||||
foreach my $f (@afiles, @mfiles, @dfiles) {
|
||||
# TODO:we need to handle removed in cvs and/or new (from git)
|
||||
my $status = `cvs -q status "$f" | grep '^File: '`;
|
||||
|
||||
unless ($status =~ m/Status: Up-to-date$/) {
|
||||
$dirty = 1;
|
||||
warn "File $f not up to date in your CVS checkout!\n";
|
||||
}
|
||||
}
|
||||
if ($dirty) {
|
||||
die "Exiting: your CVS tree is not clean for this merge.";
|
||||
}
|
||||
|
||||
###
|
||||
### NOTE: if you are planning to die() past this point
|
||||
### you MUST call cleanupcvs(@files) before die()
|
||||
###
|
||||
|
||||
|
||||
print "'Patching' binary files\n";
|
||||
|
||||
my @bfiles = `git-diff-tree -p $parent $commit | grep '^Binary'`;
|
||||
@bfiles = map { chomp } @bfiles;
|
||||
foreach my $f (@bfiles) {
|
||||
# check that the file in cvs matches the "old" file
|
||||
# extract the file to $tmpdir and comparre with cmp
|
||||
my $tree = `git-rev-parse $parent^{tree} `;
|
||||
chomp $tree;
|
||||
my $blob = `git-ls-tree $tree "$f" | cut -f 1 | cut -d ' ' -f 3`;
|
||||
chomp $blob;
|
||||
`git-cat-file blob $blob > $tmpdir/blob`;
|
||||
`cmp -q $f $tmpdir/blob`;
|
||||
if ($?) {
|
||||
warn "Binary file $f in CVS does not match parent.\n";
|
||||
$dirty = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
# replace with the new file
|
||||
`git-cat-file blob $blob > $f`;
|
||||
|
||||
# TODO: something smart with file modes
|
||||
|
||||
}
|
||||
if ($dirty) {
|
||||
cleanupcvs(@files);
|
||||
die "Exiting: Binary files in CVS do not match parent";
|
||||
}
|
||||
|
||||
## apply non-binary changes
|
||||
my $fuzz = $opt_p ? 0 : 2;
|
||||
|
||||
print "Patching non-binary files\n";
|
||||
print `(git-diff-tree -p $parent -p $commit | patch -p1 -F $fuzz ) 2>&1`;
|
||||
|
||||
my $dirtypatch = 0;
|
||||
if (($? >> 8) == 2) {
|
||||
cleanupcvs(@files);
|
||||
die "Exiting: Patch reported serious trouble -- you will have to apply this patch manually";
|
||||
} elsif (($? >> 8) == 1) { # some hunks failed to apply
|
||||
$dirtypatch = 1;
|
||||
}
|
||||
|
||||
foreach my $f (@afiles) {
|
||||
`cvs add $f`;
|
||||
if ($?) {
|
||||
$dirty = 1;
|
||||
warn "Failed to cvs add $f -- you may need to do it manually";
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $f (@dfiles) {
|
||||
`cvs rm -f $f`;
|
||||
if ($?) {
|
||||
$dirty = 1;
|
||||
warn "Failed to cvs rm -f $f -- you may need to do it manually";
|
||||
}
|
||||
}
|
||||
|
||||
print "Commit to CVS\n";
|
||||
my $commitfiles = join(' ', @afiles, @mfiles, @dfiles);
|
||||
my $cmd = "cvs commit -F .msg $commitfiles";
|
||||
|
||||
if ($dirtypatch) {
|
||||
print "NOTE: One or more hunks failed to apply cleanly.\n";
|
||||
print "Resolve the conflicts and then commit using:\n";
|
||||
print "\n $cmd\n\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if ($opt_c) {
|
||||
print "Autocommit\n $cmd\n";
|
||||
print `cvs commit -F .msg $commitfiles 2>&1`;
|
||||
if ($?) {
|
||||
cleanupcvs(@files);
|
||||
die "Exiting: The commit did not succeed";
|
||||
}
|
||||
print "Committed successfully to CVS\n";
|
||||
} else {
|
||||
print "Ready for you to commit, just run:\n\n $cmd\n";
|
||||
}
|
||||
sub usage {
|
||||
print STDERR <<END;
|
||||
Usage: GIT_DIR=/path/to/.git ${\basename $0} [-h] [-p] [-v] [-c] [ parent ] commit
|
||||
END
|
||||
exit(1);
|
||||
}
|
||||
|
||||
# ensure cvs is clean before we die
|
||||
sub cleanupcvs {
|
||||
my @files = @_;
|
||||
foreach my $f (@files) {
|
||||
`cvs -q update -C "$f"`;
|
||||
if ($?) {
|
||||
warn "Warning! Failed to cleanup state of $f\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -437,7 +437,11 @@ unless(-d $git_dir) {
|
||||
"Either use the correct '-o branch' option,\n".
|
||||
"or import to a new repository.\n";
|
||||
|
||||
$last_branch = basename(readlink("$git_dir/HEAD"));
|
||||
open(F, "git-symbolic-ref HEAD |") or
|
||||
die "Cannot run git-symbolic-ref: $!\n";
|
||||
chomp ($last_branch = <F>);
|
||||
$last_branch = basename($last_branch);
|
||||
close(F);
|
||||
unless($last_branch) {
|
||||
warn "Cannot read the last branch name: $! -- assuming 'master'\n";
|
||||
$last_branch = "master";
|
||||
@ -498,7 +502,7 @@ unless($pid) {
|
||||
if ($opt_P) {
|
||||
exec("cat", $opt_P);
|
||||
} else {
|
||||
exec("cvsps",@opt,"-u","-A",'--root',$opt_d,$cvs_tree);
|
||||
exec("cvsps","--norc",@opt,"-u","-A",'--root',$opt_d,$cvs_tree);
|
||||
die "Could not start cvsps: $!\n";
|
||||
}
|
||||
}
|
||||
@ -829,8 +833,7 @@ if($orig_branch) {
|
||||
print "DONE; creating $orig_branch branch\n" if $opt_v;
|
||||
system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
|
||||
unless -f "$git_dir/refs/heads/master";
|
||||
unlink("$git_dir/HEAD");
|
||||
symlink("refs/heads/$orig_branch","$git_dir/HEAD");
|
||||
system('git-update-ref', 'HEAD', "$orig_branch");
|
||||
unless ($opt_i) {
|
||||
system('git checkout');
|
||||
die "checkout failed: $?\n" if $?;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user