Compare commits
446 Commits
Author | SHA1 | Date | |
---|---|---|---|
c2f3bf071e | |||
41f93a2c90 | |||
a3431febfe | |||
4b3511b0f8 | |||
407c8eb0d0 | |||
29e4d36357 | |||
a5c21d6eb7 | |||
913419fcc6 | |||
47dd0d595d | |||
1c15afb934 | |||
1fdfd05db2 | |||
e32faa8adb | |||
ba922ccee7 | |||
d89056c258 | |||
3aadad1b32 | |||
ef1cc2cc21 | |||
42f4570c86 | |||
3af849a3da | |||
112d0bafd6 | |||
ea77e675e5 | |||
d808111ebd | |||
2247efb40b | |||
ad89721508 | |||
c054d64e87 | |||
f7087e2e7c | |||
8872f27b87 | |||
011fbc7f07 | |||
80248b2e48 | |||
01385e2758 | |||
69224716f7 | |||
68283999f8 | |||
3ae854c356 | |||
06bf6ac424 | |||
ee34518d62 | |||
06d900cf28 | |||
e5e3a9d8f9 | |||
1403959cc8 | |||
2a58a9a92e | |||
92811b5767 | |||
c6f60f991f | |||
6677c4665a | |||
8431c4eb09 | |||
988eece42a | |||
31ec6abf88 | |||
1ed91937e5 | |||
294c695d8c | |||
32d9954478 | |||
e0e3ba208d | |||
252fef7149 | |||
773b633943 | |||
9a26dbd120 | |||
2db8aaeca1 | |||
b0d3e9baaa | |||
a4adf54d38 | |||
5073eb04d6 | |||
9678faaaff | |||
3ae39ab232 | |||
7ab099d220 | |||
d20e2f161b | |||
87358b7a19 | |||
43a95cfbc9 | |||
6cf6193b45 | |||
cf1fe88ce1 | |||
4e7824b12e | |||
349701210d | |||
806f36d4d7 | |||
aa9dc7afd2 | |||
d025524d9d | |||
b3f041fb0f | |||
01f49e3453 | |||
f4f9adaea7 | |||
ed24928e12 | |||
9954f5b876 | |||
0a8b4def9a | |||
9755afbd94 | |||
803f498c03 | |||
76cead391f | |||
1e2ccd3abc | |||
180c474647 | |||
0532a5e46b | |||
86c9523305 | |||
c7a45bd20e | |||
44db136cad | |||
962537a3eb | |||
e726715a52 | |||
d28c8af623 | |||
a9572072f0 | |||
b825e6ff5d | |||
157dc07368 | |||
28e77a8164 | |||
7564577a6c | |||
eea420693b | |||
73ab46d6d0 | |||
024510c8d9 | |||
10945e006a | |||
6e33101abd | |||
3e525e6738 | |||
6df896b50a | |||
42f44b08bc | |||
1136fb5284 | |||
5744f27794 | |||
f88961a85f | |||
2777ef76be | |||
8b15e2fbc9 | |||
db9536c856 | |||
10b94e283a | |||
0f737464a6 | |||
2b86976bfd | |||
2dee581667 | |||
c82365dc6f | |||
8c667f4bb8 | |||
d839091d13 | |||
03f6c23c5e | |||
5dd7342142 | |||
31f232819f | |||
5e34c99d95 | |||
6f855371a5 | |||
d4ce5f7e50 | |||
674b28085e | |||
d972217457 | |||
56e5e9170e | |||
e293de3efb | |||
eaa54efc61 | |||
16cc50d12e | |||
68e37f8402 | |||
63ae26f87a | |||
bcaf60b25b | |||
9688a882e1 | |||
49ccb0877f | |||
128aed684d | |||
64224caf88 | |||
361c06d8f5 | |||
6bad1902f5 | |||
12bd7e78ee | |||
2fa090b6c1 | |||
5e80092f7e | |||
fd8ccbec4f | |||
d23748a6af | |||
b539c5e8fb | |||
3bd348aeea | |||
9754563ca9 | |||
e23eff8be9 | |||
a6da9395a5 | |||
be61db922a | |||
bb6d7b893e | |||
5f6da1d9d2 | |||
75a46f6b0e | |||
4a62eaed31 | |||
9c2e7c0ca2 | |||
61f693bd5a | |||
23c99d8460 | |||
8d69195124 | |||
4050c0df8e | |||
4dd5d0d9eb | |||
cd8c458947 | |||
53e7181cd9 | |||
9cebe90bc5 | |||
f13d7db4af | |||
dc5f9239f7 | |||
eb0362a467 | |||
dfa2f22f94 | |||
63d34b0b13 | |||
556cb4e583 | |||
3e15c67c90 | |||
d5eac49868 | |||
6f42f89c1f | |||
1494e03888 | |||
b270c634b7 | |||
18d1e701b7 | |||
f83df6d66e | |||
8bf14d6ef9 | |||
287f860054 | |||
7b9b4c452c | |||
9a79c5a8b4 | |||
3a2674337c | |||
4c353e890c | |||
423325a2d2 | |||
d79374c7b5 | |||
7950571ad7 | |||
e40b61fb6b | |||
7057463463 | |||
72d1216a04 | |||
d3bfdb755e | |||
4275df5170 | |||
56b5e946f2 | |||
d2abdd2647 | |||
3f41f5a9fe | |||
3ace1fe34b | |||
54dd99a127 | |||
1c2c10b6e6 | |||
57ae0d09ed | |||
a6b51f11ab | |||
10b15b86f5 | |||
ce3ca27545 | |||
c639a5548a | |||
f59846718e | |||
0f8f45cb4a | |||
2731d04883 | |||
a3e3dc4690 | |||
38ad0910a0 | |||
b5c2f30689 | |||
b34403aa97 | |||
9cac9d3689 | |||
5401f3040b | |||
0738fc2192 | |||
0501c2409d | |||
58cce8a85d | |||
15bf57a18a | |||
354b9b59b0 | |||
10637b84d9 | |||
5620518095 | |||
069b20a198 | |||
8bf2c69c2d | |||
4518bb8839 | |||
712fcc08c7 | |||
830273d10c | |||
a004d3f70f | |||
99e368b996 | |||
bf3e274873 | |||
e1355547fd | |||
034908047d | |||
b020dcd54c | |||
3e9fabc85e | |||
2c4ed386e8 | |||
99e0169206 | |||
d165fa14f0 | |||
d6ea70af77 | |||
7ea2fc47d2 | |||
eefaa4fca7 | |||
9cc2527cd2 | |||
1abacf3b5b | |||
710b7098e2 | |||
53228a5fb8 | |||
5a3277133d | |||
b191fa72ea | |||
706fe6ae03 | |||
c3e9a6534c | |||
61e2b01529 | |||
e44eb3e4c7 | |||
edf2e37002 | |||
4ca0660816 | |||
e9a45d75b5 | |||
b3cfd939c3 | |||
246cc52f38 | |||
32b5904b5f | |||
e2466376ec | |||
b45c569b6f | |||
3c5e8468a9 | |||
9ef2b3cbf6 | |||
ffb1a4bed5 | |||
3e2f62bebf | |||
f2e6f1c976 | |||
7f4bd5d831 | |||
36d277c72d | |||
90109b320d | |||
671bc1538a | |||
0dccc7dcee | |||
d327244a84 | |||
9f63892b38 | |||
f1f909e318 | |||
650e4be59b | |||
4e72dcec89 | |||
55d1eb047d | |||
56fc631939 | |||
26169747b8 | |||
b933e818e9 | |||
ca203ee7db | |||
f6bc189a45 | |||
3ae64dff68 | |||
22752e4c43 | |||
4f629539cd | |||
1644162ad5 | |||
ab9cb76f66 | |||
51b3c00e9d | |||
2d76d0d151 | |||
f359ae42ac | |||
ab5f86275c | |||
93dcab2937 | |||
2a1ddc58e4 | |||
5e7bfe2567 | |||
5d318ce6a9 | |||
ae2b0f1518 | |||
e8cc80d039 | |||
f678dd180a | |||
3a2f2bb354 | |||
874fbc3323 | |||
2c52a42dd7 | |||
ee72aeaf00 | |||
a50b870aa1 | |||
9c20a47067 | |||
b7884981f8 | |||
30c7bb249e | |||
073dab137a | |||
fbf8ac212c | |||
b99a394cd1 | |||
495473c08a | |||
2ed49d5424 | |||
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 |
5
.gitignore
vendored
5
.gitignore
vendored
@ -42,7 +42,7 @@ git-index-pack
|
|||||||
git-init-db
|
git-init-db
|
||||||
git-local-fetch
|
git-local-fetch
|
||||||
git-log
|
git-log
|
||||||
git-lost+found
|
git-lost-found
|
||||||
git-ls-files
|
git-ls-files
|
||||||
git-ls-remote
|
git-ls-remote
|
||||||
git-ls-tree
|
git-ls-tree
|
||||||
@ -60,7 +60,6 @@ git-merge-stupid
|
|||||||
git-mktag
|
git-mktag
|
||||||
git-name-rev
|
git-name-rev
|
||||||
git-mv
|
git-mv
|
||||||
git-octopus
|
|
||||||
git-pack-redundant
|
git-pack-redundant
|
||||||
git-pack-objects
|
git-pack-objects
|
||||||
git-parse-remote
|
git-parse-remote
|
||||||
@ -74,8 +73,8 @@ git-read-tree
|
|||||||
git-rebase
|
git-rebase
|
||||||
git-receive-pack
|
git-receive-pack
|
||||||
git-relink
|
git-relink
|
||||||
git-rename
|
|
||||||
git-repack
|
git-repack
|
||||||
|
git-repo-config
|
||||||
git-request-pull
|
git-request-pull
|
||||||
git-reset
|
git-reset
|
||||||
git-resolve
|
git-resolve
|
||||||
|
@ -9,6 +9,7 @@ ARTICLES += diffcore
|
|||||||
ARTICLES += howto-index
|
ARTICLES += howto-index
|
||||||
ARTICLES += repository-layout
|
ARTICLES += repository-layout
|
||||||
ARTICLES += hooks
|
ARTICLES += hooks
|
||||||
|
ARTICLES += everyday
|
||||||
# with their own formatting rules.
|
# with their own formatting rules.
|
||||||
SP_ARTICLES = glossary howto/revert-branch-rebase
|
SP_ARTICLES = glossary howto/revert-branch-rebase
|
||||||
|
|
||||||
|
@ -187,7 +187,8 @@ you would use git-rev-list and git-diff-tree like this:
|
|||||||
|
|
||||||
We have already talked about the "\--stdin" form of git-diff-tree
|
We have already talked about the "\--stdin" form of git-diff-tree
|
||||||
command that reads the list of commits and compares each commit
|
command that reads the list of commits and compares each commit
|
||||||
with its parents. The git-whatchanged command internally runs
|
with its parents (otherwise you should go back and read the tutorial).
|
||||||
|
The git-whatchanged command internally runs
|
||||||
the equivalent of the above command, and can be used like this:
|
the equivalent of the above command, and can be used like this:
|
||||||
|
|
||||||
$ git-whatchanged -p -S'if (frotz) {
|
$ git-whatchanged -p -S'if (frotz) {
|
||||||
|
@ -81,7 +81,7 @@ The "diff" formatting options can be customized via the
|
|||||||
environment variable 'GIT_DIFF_OPTS'. For example, if you
|
environment variable 'GIT_DIFF_OPTS'. For example, if you
|
||||||
prefer context diff:
|
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
|
2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the
|
||||||
|
@ -13,6 +13,19 @@
|
|||||||
--name-status::
|
--name-status::
|
||||||
Show only names and status of changed files.
|
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.
|
||||||
|
|
||||||
|
--abbrev[=<n>]::
|
||||||
|
Instead of showing the full 40-byte hexadecimal object
|
||||||
|
name in diff-raw format output and diff-tree header
|
||||||
|
lines, show only handful dhexigits prefix. This is
|
||||||
|
independent of --full-index option above, which controls
|
||||||
|
the diff-patch output format. Non default number of
|
||||||
|
digits can be specified with --abbrev=<n>.
|
||||||
|
|
||||||
-B::
|
-B::
|
||||||
Break complete rewrite changes into pairs of delete and create.
|
Break complete rewrite changes into pairs of delete and create.
|
||||||
|
|
||||||
|
441
Documentation/everyday.txt
Normal file
441
Documentation/everyday.txt
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
Everyday GIT With 20 Commands Or So
|
||||||
|
===================================
|
||||||
|
|
||||||
|
GIT suite has over 100 commands, and the manual page for each of
|
||||||
|
them discusses what the command does and how it is used in
|
||||||
|
detail, but until you know what command should be used in order
|
||||||
|
to achieve what you want to do, you cannot tell which manual
|
||||||
|
page to look at, and if you know that already you do not need
|
||||||
|
the manual.
|
||||||
|
|
||||||
|
Does that mean you need to know all of them before you can use
|
||||||
|
git? Not at all. Depending on the role you play, the set of
|
||||||
|
commands you need to know is slightly different, but in any case
|
||||||
|
what you need to learn is far smaller than the full set of
|
||||||
|
commands to carry out your day-to-day work. This document is to
|
||||||
|
serve as a cheat-sheet and a set of pointers for people playing
|
||||||
|
various roles.
|
||||||
|
|
||||||
|
<<Basic Repository>> commands are needed by people who has a
|
||||||
|
repository --- that is everybody, because every working tree of
|
||||||
|
git is a repository.
|
||||||
|
|
||||||
|
In addition, <<Individual Developer (Standalone)>> commands are
|
||||||
|
essential for anybody who makes a commit, even for somebody who
|
||||||
|
works alone.
|
||||||
|
|
||||||
|
If you work with other people, you will need commands listed in
|
||||||
|
<<Individual Developer (Participant)>> section as well.
|
||||||
|
|
||||||
|
People who play <<Integrator>> role need to learn some more
|
||||||
|
commands in addition to the above.
|
||||||
|
|
||||||
|
<<Repository Administration>> commands are for system
|
||||||
|
administrators who are responsible to care and feed git
|
||||||
|
repositories to support developers.
|
||||||
|
|
||||||
|
|
||||||
|
Basic Repository[[Basic Repository]]
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
Everybody uses these commands to feed and care git repositories.
|
||||||
|
|
||||||
|
* gitlink:git-init-db[1] or gitlink:git-clone[1] to create a
|
||||||
|
new repository.
|
||||||
|
|
||||||
|
* gitlink:git-fsck-objects[1] to validate the repository.
|
||||||
|
|
||||||
|
* gitlink:git-prune[1] to garbage collect crufts in the
|
||||||
|
repository.
|
||||||
|
|
||||||
|
* gitlink:git-repack[1] to pack loose objects for efficiency.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
Check health and remove cruft.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git fsck-objects <1>
|
||||||
|
$ git prune
|
||||||
|
$ git count-objects <2>
|
||||||
|
$ git repack <3>
|
||||||
|
$ git prune <4>
|
||||||
|
|
||||||
|
<1> running without "--full" is usually cheap and assures the
|
||||||
|
repository health reasonably well.
|
||||||
|
<2> check how many loose objects there are and how much
|
||||||
|
diskspace is wasted by not repacking.
|
||||||
|
<3> without "-a" repacks incrementally. repacking every 4-5MB
|
||||||
|
of loose objects accumulation may be a good rule of thumb.
|
||||||
|
<4> after repack, prune removes the duplicate loose objects.
|
||||||
|
------------
|
||||||
|
|
||||||
|
Repack a small project into single pack.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git repack -a -d <1>
|
||||||
|
$ git prune
|
||||||
|
|
||||||
|
<1> pack all the objects reachable from the refs into one pack
|
||||||
|
and remove unneeded other packs
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Individual Developer (Standalone)[[Individual Developer (Standalone)]]
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
A standalone individual developer does not exchange patches with
|
||||||
|
other poeple, and works alone in a single repository, using the
|
||||||
|
following commands.
|
||||||
|
|
||||||
|
* gitlink:git-show-branch[1] to see where you are.
|
||||||
|
|
||||||
|
* gitlink:git-log[1] to see what happened.
|
||||||
|
|
||||||
|
* gitlink:git-whatchanged[1] to find out where things have
|
||||||
|
come from.
|
||||||
|
|
||||||
|
* gitlink:git-checkout[1] and gitlink:git-branch[1] to switch
|
||||||
|
branches.
|
||||||
|
|
||||||
|
* gitlink:git-add[1] and gitlink:git-update-index[1] to manage
|
||||||
|
the index file.
|
||||||
|
|
||||||
|
* gitlink:git-diff[1] and gitlink:git-status[1] to see what
|
||||||
|
you are in the middle of doing.
|
||||||
|
|
||||||
|
* gitlink:git-commit[1] to advance the current branch.
|
||||||
|
|
||||||
|
* gitlink:git-reset[1] and gitlink:git-checkout[1] (with
|
||||||
|
pathname parameters) to undo changes.
|
||||||
|
|
||||||
|
* gitlink:git-pull[1] with "." as the remote to merge between
|
||||||
|
local branches.
|
||||||
|
|
||||||
|
* gitlink:git-rebase[1] to maintain topic branches.
|
||||||
|
|
||||||
|
* gitlink:git-tag[1] to mark known point.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
Extract a tarball and create a working tree and a new repository to keep track of it.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ tar zxf frotz.tar.gz
|
||||||
|
$ cd frotz
|
||||||
|
$ git-init-db
|
||||||
|
$ git add . <1>
|
||||||
|
$ git commit -m 'import of frotz source tree.'
|
||||||
|
$ git tag v2.43 <2>
|
||||||
|
|
||||||
|
<1> add everything under the current directory.
|
||||||
|
<2> make a lightweight, unannotated tag.
|
||||||
|
------------
|
||||||
|
|
||||||
|
Create a topic branch and develop.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git checkout -b alsa-audio <1>
|
||||||
|
$ edit/compile/test
|
||||||
|
$ git checkout -- curses/ux_audio_oss.c <2>
|
||||||
|
$ git add curses/ux_audio_alsa.c <3>
|
||||||
|
$ edit/compile/test
|
||||||
|
$ git diff <4>
|
||||||
|
$ git commit -a -s <5>
|
||||||
|
$ edit/compile/test
|
||||||
|
$ git reset --soft HEAD^ <6>
|
||||||
|
$ edit/compile/test
|
||||||
|
$ git diff ORIG_HEAD <7>
|
||||||
|
$ git commit -a -c ORIG_HEAD <8>
|
||||||
|
$ git checkout master <9>
|
||||||
|
$ git pull . alsa-audio <10>
|
||||||
|
$ git log --since='3 days ago' <11>
|
||||||
|
$ git log v2.43.. curses/ <12>
|
||||||
|
|
||||||
|
<1> create a new topic branch.
|
||||||
|
<2> revert your botched changes in "curses/ux_audio_oss.c".
|
||||||
|
<3> you need to tell git if you added a new file; removal and
|
||||||
|
modification will be caught if you do "commit -a" later.
|
||||||
|
<4> to see what changes you are committing.
|
||||||
|
<5> commit everything as you have tested, with your sign-off.
|
||||||
|
<6> take the last commit back, keeping what is in the working tree.
|
||||||
|
<7> look at the changes since the premature commit we took back.
|
||||||
|
<8> redo the commit undone in the previous step, using the message
|
||||||
|
you originally wrote.
|
||||||
|
<9> switch to the master branch.
|
||||||
|
<10> merge a topic branch into your master branch
|
||||||
|
<11> review commit logs; other forms to limit output can be
|
||||||
|
combined and include --max-count=10 (show 10 commits), --until='2005-12-10'.
|
||||||
|
<12> view only the changes that touch what's in curses/
|
||||||
|
directory, since v2.43 tag.
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Individual Developer (Participant)[[Individual Developer (Participant)]]
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
A developer working as a participant in a group project needs to
|
||||||
|
learn how to communicate with others, and uses these commands in
|
||||||
|
addition to the ones needed by a standalone developer.
|
||||||
|
|
||||||
|
* gitlink:git-clone[1] from the upstream to prime your local
|
||||||
|
repository.
|
||||||
|
|
||||||
|
* gitlink:git-pull[1] and gitlink:git-fetch[1] from "origin"
|
||||||
|
to keep up-to-date with the upstream.
|
||||||
|
|
||||||
|
* gitlink:git-push[1] to shared repository, if you adopt CVS
|
||||||
|
style shared repository workflow.
|
||||||
|
|
||||||
|
* gitlink:git-format-patch[1] to prepare e-mail submission, if
|
||||||
|
you adopt Linux kernel-style public forum workflow.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
Clone the upstream and work on it. Feed changes to upstream.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git clone git://git.kernel.org/pub/scm/.../torvalds/linux-2.6 my2.6
|
||||||
|
$ cd my2.6
|
||||||
|
$ edit/compile/test; git commit -a -s <1>
|
||||||
|
$ git format-patch origin <2>
|
||||||
|
$ git pull <3>
|
||||||
|
$ git whatchanged -p ORIG_HEAD.. arch/i386 include/asm-i386 <4>
|
||||||
|
$ git pull git://git.kernel.org/pub/.../jgarzik/libata-dev.git ALL <5>
|
||||||
|
$ git reset --hard ORIG_HEAD <6>
|
||||||
|
$ git prune <7>
|
||||||
|
$ git fetch --tags <8>
|
||||||
|
|
||||||
|
<1> repeat as needed.
|
||||||
|
<2> extract patches from your branch for e-mail submission.
|
||||||
|
<3> "pull" fetches from "origin" by default and merges into the
|
||||||
|
current branch.
|
||||||
|
<4> immediately after pulling, look at the changes done upstream
|
||||||
|
since last time we checked, only in the
|
||||||
|
area we are interested in.
|
||||||
|
<5> fetch from a specific branch from a specific repository and merge.
|
||||||
|
<6> revert the pull.
|
||||||
|
<7> garbage collect leftover objects from reverted pull.
|
||||||
|
<8> from time to time, obtain official tags from the "origin"
|
||||||
|
and store them under .git/refs/tags/.
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Push into another repository.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
satellite$ git clone mothership:frotz/.git frotz <1>
|
||||||
|
satellite$ cd frotz
|
||||||
|
satellite$ cat .git/remotes/origin <2>
|
||||||
|
URL: mothership:frotz/.git
|
||||||
|
Pull: master:origin
|
||||||
|
satellite$ echo 'Push: master:satellite' >>.git/remotes/origin <3>
|
||||||
|
satellite$ edit/compile/test/commit
|
||||||
|
satellite$ git push origin <4>
|
||||||
|
|
||||||
|
mothership$ cd frotz
|
||||||
|
mothership$ git checkout master
|
||||||
|
mothership$ git pull . satellite <5>
|
||||||
|
|
||||||
|
<1> mothership machine has a frotz repository under your home
|
||||||
|
directory; clone from it to start a repository on the satellite
|
||||||
|
machine.
|
||||||
|
<2> clone creates this file by default. It arranges "git pull"
|
||||||
|
to fetch and store the master branch head of mothership machine
|
||||||
|
to local "origin" branch.
|
||||||
|
<3> arrange "git push" to push local "master" branch to
|
||||||
|
"satellite" branch of the mothership machine.
|
||||||
|
<4> push will stash our work away on "satellite" branch on the
|
||||||
|
mothership machine. You could use this as a back-up method.
|
||||||
|
<5> on mothership machine, merge the work done on the satellite
|
||||||
|
machine into the master branch.
|
||||||
|
------------
|
||||||
|
|
||||||
|
Branch off of a specific tag.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git checkout -b private2.6.14 v2.6.14 <1>
|
||||||
|
$ edit/compile/test; git commit -a
|
||||||
|
$ git checkout master
|
||||||
|
$ git format-patch -k -m --stdout v2.6.14..private2.6.14 |
|
||||||
|
git am -3 -k <2>
|
||||||
|
|
||||||
|
<1> create a private branch based on a well known (but somewhat behind)
|
||||||
|
tag.
|
||||||
|
<2> forward port all changes in private2.6.14 branch to master branch
|
||||||
|
without a formal "merging".
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Integrator[[Integrator]]
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
A fairly central person acting as the integrator in a group
|
||||||
|
project receives changes made by others, reviews and integrates
|
||||||
|
them and publishes the result for others to use, using these
|
||||||
|
commands in addition to the ones needed by participants.
|
||||||
|
|
||||||
|
* gitlink:git-am[1] to apply patches e-mailed in from your
|
||||||
|
contributors.
|
||||||
|
|
||||||
|
* gitlink:git-pull[1] to merge from your trusted lieutenants.
|
||||||
|
|
||||||
|
* gitlink:git-format-patch[1] to prepare and send suggested
|
||||||
|
alternative to contributors.
|
||||||
|
|
||||||
|
* gitlink:git-revert[1] to undo botched commits.
|
||||||
|
|
||||||
|
* gitlink:git-push[1] to publish the bleeding edge.
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
My typical GIT day.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git status <1>
|
||||||
|
$ git show-branch <2>
|
||||||
|
$ mailx <3>
|
||||||
|
& s 2 3 4 5 ./+to-apply
|
||||||
|
& s 7 8 ./+hold-linus
|
||||||
|
& q
|
||||||
|
$ git checkout master
|
||||||
|
$ git am -3 -i -s -u ./+to-apply <4>
|
||||||
|
$ compile/test
|
||||||
|
$ git checkout -b hold/linus && git am -3 -i -s -u ./+hold-linus <5>
|
||||||
|
$ git checkout topic/one && git rebase master <6>
|
||||||
|
$ git checkout pu && git reset --hard master <7>
|
||||||
|
$ git pull . topic/one topic/two && git pull . hold/linus <8>
|
||||||
|
$ git checkout maint
|
||||||
|
$ git cherry-pick master~4 <9>
|
||||||
|
$ compile/test
|
||||||
|
$ git tag -s -m 'GIT 0.99.9x' v0.99.9x <10>
|
||||||
|
$ git fetch ko && git show-branch master maint 'tags/ko-*' <11>
|
||||||
|
$ git push ko <12>
|
||||||
|
$ git push ko v0.99.9x <13>
|
||||||
|
|
||||||
|
<1> see what I was in the middle of doing, if any.
|
||||||
|
<2> see what topic branches I have and think about how ready
|
||||||
|
they are.
|
||||||
|
<3> read mails, save ones that are applicable, and save others
|
||||||
|
that are not quite ready.
|
||||||
|
<4> apply them, interactively, with my sign-offs.
|
||||||
|
<5> create topic branch as needed and apply, again with my
|
||||||
|
sign-offs.
|
||||||
|
<6> rebase internal topic branch that has not been merged to the
|
||||||
|
master, nor exposed as a part of a stable branch.
|
||||||
|
<7> restart "pu" every time from the master.
|
||||||
|
<8> and bundle topic branches still cooking.
|
||||||
|
<9> backport a critical fix.
|
||||||
|
<10> create a signed tag.
|
||||||
|
<11> make sure I did not accidentally rewind master beyond what I
|
||||||
|
already pushed out. "ko" shorthand points at the repository I have
|
||||||
|
at kernel.org, and looks like this:
|
||||||
|
$ cat .git/remotes/ko
|
||||||
|
URL: kernel.org:/pub/scm/git/git.git
|
||||||
|
Pull: master:refs/tags/ko-master
|
||||||
|
Pull: maint:refs/tags/ko-maint
|
||||||
|
Push: master
|
||||||
|
Push: +pu
|
||||||
|
Push: maint
|
||||||
|
In the output from "git show-branch", "master" should have
|
||||||
|
everything "ko-master" has.
|
||||||
|
<12> push out the bleeding edge.
|
||||||
|
<13> push the tag out, too.
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Repository Administration[[Repository Administration]]
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
A repository administrator uses the following tools to set up
|
||||||
|
and maintain access to the repository by developers.
|
||||||
|
|
||||||
|
* gitlink:git-daemon[1] to allow anonymous download from
|
||||||
|
repository.
|
||||||
|
|
||||||
|
* gitlink:git-shell[1] can be used as a 'restricted login shell'
|
||||||
|
for shared central repository users.
|
||||||
|
|
||||||
|
link:howto/update-hook-example.txt[update hook howto] has a good
|
||||||
|
example of managing a shared central repository.
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
Run git-daemon to serve /pub/scm from inetd.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ grep git /etc/inet.conf
|
||||||
|
git stream tcp nowait nobody \
|
||||||
|
/usr/bin/git-daemon git-daemon --inetd --syslog --export-all /pub/scm
|
||||||
|
------------
|
||||||
|
+
|
||||||
|
The actual configuration line should be on one line.
|
||||||
|
|
||||||
|
Give push/pull only access to developers.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ grep git /etc/passwd <1>
|
||||||
|
alice:x:1000:1000::/home/alice:/usr/bin/git-shell
|
||||||
|
bob:x:1001:1001::/home/bob:/usr/bin/git-shell
|
||||||
|
cindy:x:1002:1002::/home/cindy:/usr/bin/git-shell
|
||||||
|
david:x:1003:1003::/home/david:/usr/bin/git-shell
|
||||||
|
$ grep git /etc/shells <2>
|
||||||
|
/usr/bin/git-shell
|
||||||
|
|
||||||
|
<1> log-in shell is set to /usr/bin/git-shell, which does not
|
||||||
|
allow anything but "git push" and "git pull". The users should
|
||||||
|
get an ssh access to the machine.
|
||||||
|
<2> in many distributions /etc/shells needs to list what is used
|
||||||
|
as the login shell.
|
||||||
|
------------
|
||||||
|
|
||||||
|
CVS-style shared repository.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ grep git /etc/group <1>
|
||||||
|
git:x:9418:alice,bob,cindy,david
|
||||||
|
$ cd /home/devo.git
|
||||||
|
$ ls -l <2>
|
||||||
|
lrwxrwxrwx 1 david git 17 Dec 4 22:40 HEAD -> refs/heads/master
|
||||||
|
drwxrwsr-x 2 david git 4096 Dec 4 22:40 branches
|
||||||
|
-rw-rw-r-- 1 david git 84 Dec 4 22:40 config
|
||||||
|
-rw-rw-r-- 1 david git 58 Dec 4 22:40 description
|
||||||
|
drwxrwsr-x 2 david git 4096 Dec 4 22:40 hooks
|
||||||
|
-rw-rw-r-- 1 david git 37504 Dec 4 22:40 index
|
||||||
|
drwxrwsr-x 2 david git 4096 Dec 4 22:40 info
|
||||||
|
drwxrwsr-x 4 david git 4096 Dec 4 22:40 objects
|
||||||
|
drwxrwsr-x 4 david git 4096 Nov 7 14:58 refs
|
||||||
|
drwxrwsr-x 2 david git 4096 Dec 4 22:40 remotes
|
||||||
|
$ ls -l hooks/update <3>
|
||||||
|
-r-xr-xr-x 1 david git 3536 Dec 4 22:40 update
|
||||||
|
$ cat info/allowed-users <4>
|
||||||
|
refs/heads/master alice\|cindy
|
||||||
|
refs/heads/doc-update bob
|
||||||
|
refs/tags/v[0-9]* david
|
||||||
|
|
||||||
|
<1> place the developers into the same git group.
|
||||||
|
<2> and make the shared repository writable by the group.
|
||||||
|
<3> use update-hook example by Carl from Documentation/howto/
|
||||||
|
for branch policy control.
|
||||||
|
<4> alice and cindy can push into master, only bob can push into doc-update.
|
||||||
|
david is the release manager and is the only person who can
|
||||||
|
create and push version tags.
|
||||||
|
------------
|
||||||
|
|
||||||
|
HTTP server to support dumb protocol transfer.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
dev$ git update-server-info <1>
|
||||||
|
dev$ ftp user@isp.example.com <2>
|
||||||
|
ftp> cp -r .git /home/user/myproject.git
|
||||||
|
|
||||||
|
<1> make sure your info/refs and objects/info/packs are up-to-date
|
||||||
|
<2> upload to public HTTP server hosted by your ISP.
|
||||||
|
------------
|
@ -4,11 +4,18 @@
|
|||||||
option old data in `.git/FETCH_HEAD` will be overwritten.
|
option old data in `.git/FETCH_HEAD` will be overwritten.
|
||||||
|
|
||||||
-f, \--force::
|
-f, \--force::
|
||||||
|
When `git-fetch` is used with `<rbranch>:<lbranch>`
|
||||||
|
refspec, it refuses to update the local branch
|
||||||
|
`<lbranch>` unless the remote branch `<rbranch>` it
|
||||||
|
fetches is a descendant of `<lbranch>`. This option
|
||||||
|
overrides that check.
|
||||||
|
|
||||||
-t, \--tags::
|
-t, \--tags::
|
||||||
By default, the git core utilities will not fetch and store
|
By default, the git core utilities will not fetch and store
|
||||||
tags under the same name as the remote repository; ask it
|
tags under the same name as the remote repository; ask it
|
||||||
to do so using `--tags`.
|
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::
|
-u, \--update-head-ok::
|
||||||
By default `git-fetch` refuses to update the head which
|
By default `git-fetch` refuses to update the head which
|
||||||
|
@ -8,8 +8,8 @@ git-am - Apply a series of patches in a mailbox
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-am' [--signoff] [--dotest=<dir>] [--utf8] [--3way] <mbox>...
|
'git-am' [--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way] <mbox>...
|
||||||
'git-am' [--skip]
|
'git-am' [--skip | --resolved]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -28,9 +28,13 @@ OPTIONS
|
|||||||
area to store extracted patches.
|
area to store extracted patches.
|
||||||
|
|
||||||
--utf8, --keep::
|
--utf8, --keep::
|
||||||
Pass `--utf8` and `--keep` flags to `git-mailinfo` (see
|
Pass `-u` and `-k` flags to `git-mailinfo` (see
|
||||||
gitlink:git-mailinfo[1]).
|
gitlink:git-mailinfo[1]).
|
||||||
|
|
||||||
|
--binary::
|
||||||
|
Pass `--allow-binary-replacement` flag to `git-apply`
|
||||||
|
(see gitlink:git-apply[1]).
|
||||||
|
|
||||||
--3way::
|
--3way::
|
||||||
When the patch does not apply cleanly, fall back on
|
When the patch does not apply cleanly, fall back on
|
||||||
3-way merge, if the patch records the identity of blobs
|
3-way merge, if the patch records the identity of blobs
|
||||||
@ -44,6 +48,13 @@ OPTIONS
|
|||||||
--interactive::
|
--interactive::
|
||||||
Run interactively, just like git-applymbox.
|
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
|
DISCUSSION
|
||||||
----------
|
----------
|
||||||
@ -56,12 +67,9 @@ recover from this in one of two ways:
|
|||||||
. skip the current one by re-running the command with '--skip'
|
. skip the current one by re-running the command with '--skip'
|
||||||
option.
|
option.
|
||||||
|
|
||||||
. hand resolve the conflict in the working directory, run 'git
|
. hand resolve the conflict in the working directory, and update
|
||||||
diff HEAD' to extract the merge result into a patch form and
|
the index file to bring it in a state that the patch should
|
||||||
replacing the patch in .dotest/patch file. After doing this,
|
have produced. Then run the command with '--resolved' option.
|
||||||
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.
|
|
||||||
|
|
||||||
The command refuses to process new mailboxes while `.dotest`
|
The command refuses to process new mailboxes while `.dotest`
|
||||||
directory exists, so if you decide to start over from scratch,
|
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
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [-z] [<patch>...]
|
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [<patch>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -79,6 +79,17 @@ OPTIONS
|
|||||||
the result with this option, which would apply the
|
the result with this option, which would apply the
|
||||||
deletion part but not addition part.
|
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
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org>
|
Written by Linus Torvalds <torvalds@osdl.org>
|
||||||
|
@ -8,7 +8,8 @@ git-archimport - Import an Arch repository into git
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
`git-archimport` [ -h ] [ -v ] [ -T ] [ -t tempdir ]
|
`git-archimport` [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
|
||||||
|
[ -D depth ] [ -t tempdir ]
|
||||||
<archive/branch> [ <archive/branch> ]
|
<archive/branch> [ <archive/branch> ]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -63,6 +64,26 @@ OPTIONS
|
|||||||
Many tags. Will create a tag for every commit, reflecting the commit
|
Many tags. Will create a tag for every commit, reflecting the commit
|
||||||
name in the Arch repository.
|
name in the Arch repository.
|
||||||
|
|
||||||
|
-f::
|
||||||
|
Use the fast patchset import strategy. This can be significantly
|
||||||
|
faster for large trees, but cannot handle directory renames or
|
||||||
|
permissions changes. The default strategy is slow and safe.
|
||||||
|
|
||||||
|
-o::
|
||||||
|
Use this for compatibility with old-style branch names used by
|
||||||
|
earlier versions of git-archimport. Old-style branch names
|
||||||
|
were category--branch, whereas new-style branch names are
|
||||||
|
archive,category--branch--version.
|
||||||
|
|
||||||
|
-D <depth>::
|
||||||
|
Follow merge ancestry and attempt to import trees that have been
|
||||||
|
merged from. Specify a depth greater than 1 if patch logs have been
|
||||||
|
pruned.
|
||||||
|
|
||||||
|
-a::
|
||||||
|
Attempt to auto-register archives at http://mirrors.sourcecontrol.net
|
||||||
|
This is particularly useful with the -D option.
|
||||||
|
|
||||||
-t <tmpdir>::
|
-t <tmpdir>::
|
||||||
Override the default tempdir.
|
Override the default tempdir.
|
||||||
|
|
||||||
|
@ -8,16 +8,21 @@ git-bisect - Find the change that introduced a bug
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git bisect' start
|
'git bisect' <subcommand> <options>
|
||||||
'git bisect' bad <rev>
|
|
||||||
'git bisect' good <rev>
|
|
||||||
'git bisect' reset [<branch>]
|
|
||||||
'git bisect' visualize
|
|
||||||
'git bisect' replay <logfile>
|
|
||||||
'git bisect' log
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
The command takes various subcommands, and different options
|
||||||
|
depending on the subcommand:
|
||||||
|
|
||||||
|
git bisect start [<paths>...]
|
||||||
|
git bisect bad <rev>
|
||||||
|
git bisect good <rev>
|
||||||
|
git bisect reset [<branch>]
|
||||||
|
git bisect visualize
|
||||||
|
git bisect replay <logfile>
|
||||||
|
git bisect log
|
||||||
|
|
||||||
This command uses 'git-rev-list --bisect' option to help drive
|
This command uses 'git-rev-list --bisect' option to help drive
|
||||||
the binary search process to find which change introduced a bug,
|
the binary search process to find which change introduced a bug,
|
||||||
given an old "good" commit object name and a later "bad" commit
|
given an old "good" commit object name and a later "bad" commit
|
||||||
@ -26,10 +31,10 @@ object name.
|
|||||||
The way you use it is:
|
The way you use it is:
|
||||||
|
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
git bisect start
|
$ git bisect start
|
||||||
git bisect bad # Current version is bad
|
$ git bisect bad # Current version is bad
|
||||||
git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version
|
$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version
|
||||||
# tested that was good
|
# tested that was good
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
When you give at least one bad and one good versions, it will
|
When you give at least one bad and one good versions, it will
|
||||||
@ -43,7 +48,7 @@ and check out the state in the middle. Now, compile that kernel, and boot
|
|||||||
it. Now, let's say that this booted kernel works fine, then just do
|
it. Now, let's say that this booted kernel works fine, then just do
|
||||||
|
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
git bisect good # this one is good
|
$ git bisect good # this one is good
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
which will now say
|
which will now say
|
||||||
@ -62,7 +67,7 @@ kernel rev in "refs/bisect/bad".
|
|||||||
Oh, and then after you want to reset to the original head, do a
|
Oh, and then after you want to reset to the original head, do a
|
||||||
|
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
git bisect reset
|
$ git bisect reset
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
to get back to the master branch, instead of being in one of the bisection
|
to get back to the master branch, instead of being in one of the bisection
|
||||||
@ -72,7 +77,9 @@ not using some old bisection branch).
|
|||||||
|
|
||||||
During the bisection process, you can say
|
During the bisection process, you can say
|
||||||
|
|
||||||
git bisect visualize
|
------------
|
||||||
|
$ git bisect visualize
|
||||||
|
------------
|
||||||
|
|
||||||
to see the currently remaining suspects in `gitk`.
|
to see the currently remaining suspects in `gitk`.
|
||||||
|
|
||||||
@ -80,11 +87,40 @@ The good/bad input is logged, and `git bisect
|
|||||||
log` shows what you have done so far. You can truncate its
|
log` shows what you have done so far. You can truncate its
|
||||||
output somewhere and save it in a file, and run
|
output somewhere and save it in a file, and run
|
||||||
|
|
||||||
git bisect replay that-file
|
------------
|
||||||
|
$ git bisect replay that-file
|
||||||
|
------------
|
||||||
|
|
||||||
if you find later you made a mistake telling good/bad about a
|
if you find later you made a mistake telling good/bad about a
|
||||||
revision.
|
revision.
|
||||||
|
|
||||||
|
If in a middle of bisect session, you know what the bisect
|
||||||
|
suggested to try next is not a good one to test (e.g. the change
|
||||||
|
the commit introduces is known not to work in your environment
|
||||||
|
and you know it does not have anything to do with the bug you
|
||||||
|
are chasing), you may want to find a near-by commit and try that
|
||||||
|
instead. It goes something like this:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git bisect good/bad # previous round was good/bad.
|
||||||
|
Bisecting: 337 revisions left to test after this
|
||||||
|
$ git bisect visualize # oops, that is uninteresting.
|
||||||
|
$ git reset --hard HEAD~3 # try 3 revs before what
|
||||||
|
# was suggested
|
||||||
|
------------
|
||||||
|
|
||||||
|
Then compile and test the one you chose to try. After that,
|
||||||
|
tell bisect what the result was as usual.
|
||||||
|
|
||||||
|
You can further cut down the number of trials if you know what
|
||||||
|
part of the tree is involved in the problem you are tracking
|
||||||
|
down, by giving paths parameters when you say `bisect start`,
|
||||||
|
like this:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git bisect start arch/i386 include/asm-i386
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -3,11 +3,11 @@ git-branch(1)
|
|||||||
|
|
||||||
NAME
|
NAME
|
||||||
----
|
----
|
||||||
git-branch - Create a new branch.
|
git-branch - Create a new branch, or remove an old one.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-branch' [<branchname> [start-point]]
|
'git-branch' [-d | -D] [<branchname> [start-point]]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -19,11 +19,44 @@ created, otherwise it will be created at the current HEAD.
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
-d::
|
||||||
|
Delete a branch. The branch must be fully merged.
|
||||||
|
|
||||||
|
-D::
|
||||||
|
Delete a branch irrespective of its index status.
|
||||||
|
|
||||||
<branchname>::
|
<branchname>::
|
||||||
The name of the branch to create.
|
The name of the branch to create or delete.
|
||||||
|
|
||||||
start-point::
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
Start development off of a know tag::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6
|
||||||
|
$ cd my2.6
|
||||||
|
$ git branch my2.6.14 v2.6.14 <1>
|
||||||
|
$ git checkout my2.6.14
|
||||||
|
|
||||||
|
<1> These two steps are the same as "checkout -b my2.6.14 v2.6.14".
|
||||||
|
------------
|
||||||
|
|
||||||
|
Delete unneeded branch::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git clone git://git.kernel.org/.../git.git my.git
|
||||||
|
$ cd my.git
|
||||||
|
$ git branch -D todo <1>
|
||||||
|
|
||||||
|
<1> delete todo branch even if the "master" branch does not have all
|
||||||
|
commits from todo branch.
|
||||||
|
------------
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -8,7 +8,7 @@ git-cat-file - Provide content or type information for repository objects
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-cat-file' (-t | -s | <type>) <object>
|
'git-cat-file' (-t | -s | -e | <type>) <object>
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -29,6 +29,10 @@ OPTIONS
|
|||||||
Instead of the content, show the object size identified by
|
Instead of the content, show the object size identified by
|
||||||
<object>.
|
<object>.
|
||||||
|
|
||||||
|
-e::
|
||||||
|
Suppress all output; instead exit with zero status if <object>
|
||||||
|
exists and is a valid object.
|
||||||
|
|
||||||
<type>::
|
<type>::
|
||||||
Typically this matches the real type of <object> but asking
|
Typically this matches the real type of <object> but asking
|
||||||
for a type that can trivially be dereferenced from the given
|
for a type that can trivially be dereferenced from the given
|
||||||
@ -39,8 +43,11 @@ OPTIONS
|
|||||||
|
|
||||||
OUTPUT
|
OUTPUT
|
||||||
------
|
------
|
||||||
If '-t' is specified, one of the <type>. If '-s' is specified,
|
If '-t' is specified, one of the <type>.
|
||||||
the size of the <object> in bytes.
|
|
||||||
|
If '-s' is specified, the size of the <object> in bytes.
|
||||||
|
|
||||||
|
If '-e' is specified, no output.
|
||||||
|
|
||||||
Otherwise the raw (though uncompressed) contents of the <object> will
|
Otherwise the raw (though uncompressed) contents of the <object> will
|
||||||
be returned.
|
be returned.
|
||||||
|
@ -26,13 +26,15 @@ imposes the following rules on how refs are named:
|
|||||||
|
|
||||||
. It cannot have ASCII control character (i.e. bytes whose
|
. It cannot have ASCII control character (i.e. bytes whose
|
||||||
values are lower than \040, or \177 `DEL`), space, tilde `~`,
|
values are lower than \040, or \177 `DEL`), space, tilde `~`,
|
||||||
caret `{caret}`, or colon `:` anywhere;
|
caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
|
||||||
|
or open bracket `[` anywhere;
|
||||||
|
|
||||||
. It cannot end with a slash `/`.
|
. It cannot end with a slash `/`.
|
||||||
|
|
||||||
These rules makes it easy for shell script based tools to parse
|
These rules makes it easy for shell script based tools to parse
|
||||||
refnames, and also avoids ambiguities in certain refname
|
refnames, pathname expansion by the shell when a refname is used
|
||||||
expressions (see gitlink:git-rev-parse[1]). Namely:
|
unquoted (by mistake), and also avoids ambiguities in certain
|
||||||
|
refname expressions (see gitlink:git-rev-parse[1]). Namely:
|
||||||
|
|
||||||
. double-dot `..` are often used as in `ref1..ref2`, and in some
|
. double-dot `..` are often used as in `ref1..ref2`, and in some
|
||||||
context this notation means `{caret}ref1 ref2` (i.e. not in
|
context this notation means `{caret}ref1 ref2` (i.e. not in
|
||||||
|
@ -9,7 +9,7 @@ git-checkout-index - Copy files from the index to the working directory
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
|
'git-checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
|
||||||
[--] <file>...
|
[--stage=<number>] [--] <file>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -18,21 +18,21 @@ Will copy all files listed from the index to the working directory
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
-u::
|
-u|--index::
|
||||||
update stat information for the checked out entries in
|
update stat information for the checked out entries in
|
||||||
the index file.
|
the index file.
|
||||||
|
|
||||||
-q::
|
-q|--quiet::
|
||||||
be quiet if files exist or are not in the index
|
be quiet if files exist or are not in the index
|
||||||
|
|
||||||
-f::
|
-f|--force::
|
||||||
forces overwrite of existing files
|
forces overwrite of existing files
|
||||||
|
|
||||||
-a::
|
-a|--all::
|
||||||
checks out all files in the index. Cannot be used
|
checks out all files in the index. Cannot be used
|
||||||
together with explicit filenames.
|
together with explicit filenames.
|
||||||
|
|
||||||
-n::
|
-n|--no-create::
|
||||||
Don't checkout new files, only refresh files already checked
|
Don't checkout new files, only refresh files already checked
|
||||||
out.
|
out.
|
||||||
|
|
||||||
@ -40,58 +40,80 @@ OPTIONS
|
|||||||
When creating files, prepend <string> (usually a directory
|
When creating files, prepend <string> (usually a directory
|
||||||
including a trailing /)
|
including a trailing /)
|
||||||
|
|
||||||
|
--stage=<number>::
|
||||||
|
Instead of checking out unmerged entries, copy out the
|
||||||
|
files from named stage. <number> must be between 1 and 3.
|
||||||
|
|
||||||
--::
|
--::
|
||||||
Do not interpret any more arguments as options.
|
Do not interpret any more arguments as options.
|
||||||
|
|
||||||
The order of the flags used to matter, but not anymore.
|
The order of the flags used to matter, but not anymore.
|
||||||
|
|
||||||
Just doing "git-checkout-index" does nothing. You probably meant
|
Just doing `git-checkout-index` does nothing. You probably meant
|
||||||
"git-checkout-index -a". And if you want to force it, you want
|
`git-checkout-index -a`. And if you want to force it, you want
|
||||||
"git-checkout-index -f -a".
|
`git-checkout-index -f -a`.
|
||||||
|
|
||||||
Intuitiveness is not the goal here. Repeatability is. The reason for
|
Intuitiveness is not the goal here. Repeatability is. The reason for
|
||||||
the "no arguments means no work" thing is that from scripts you are
|
the "no arguments means no work" behavior is that from scripts you are
|
||||||
supposed to be able to do things like:
|
supposed to be able to do:
|
||||||
|
|
||||||
find . -name '*.h' -print0 | xargs -0 git-checkout-index -f --
|
----------------
|
||||||
|
$ find . -name '*.h' -print0 | xargs -0 git-checkout-index -f --
|
||||||
|
----------------
|
||||||
|
|
||||||
which will force all existing `*.h` files to be replaced with their
|
which will force all existing `*.h` files to be replaced with their
|
||||||
cached copies. If an empty command line implied "all", then this would
|
cached copies. If an empty command line implied "all", then this would
|
||||||
force-refresh everything in the index, 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:
|
The `--` is just a good idea when you know the rest will be filenames;
|
||||||
|
it will prevent problems with a filename of, for example, `-a`.
|
||||||
|
Using `--` is probably a good policy in scripts.
|
||||||
|
|
||||||
git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
|
|
||||||
|
|
||||||
Oh, and the "--" is just a good idea when you know the rest will be
|
EXAMPLES
|
||||||
filenames. Just so that you wouldn't have a filename of "-a" causing
|
--------
|
||||||
problems (not possible in the above example, but get used to it in
|
To update and refresh only the files already checked out::
|
||||||
scripting!).
|
+
|
||||||
|
----------------
|
||||||
|
$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
|
||||||
|
----------------
|
||||||
|
|
||||||
The prefix ability basically makes it trivial to use
|
Using `git-checkout-index` to "export an entire tree"::
|
||||||
git-checkout-index as an "export as tree" function. Just read the
|
The prefix ability basically makes it trivial to use
|
||||||
desired tree into the index, and do a
|
`git-checkout-index` as an "export as tree" function.
|
||||||
|
Just read the desired tree into the index, and do:
|
||||||
git-checkout-index --prefix=git-export-dir/ -a
|
+
|
||||||
|
----------------
|
||||||
and git-checkout-index will "export" the index into the specified
|
$ git-checkout-index --prefix=git-export-dir/ -a
|
||||||
|
----------------
|
||||||
|
+
|
||||||
|
`git-checkout-index` will "export" the index into the specified
|
||||||
directory.
|
directory.
|
||||||
|
+
|
||||||
|
The final "/" is important. The exported name is literally just
|
||||||
|
prefixed with the specified string. Contrast this with the
|
||||||
|
following example.
|
||||||
|
|
||||||
NOTE The final "/" is important. The exported name is literally just
|
Export files with a prefix::
|
||||||
prefixed with the specified string, so you can also do something like
|
+
|
||||||
|
----------------
|
||||||
|
$ git-checkout-index --prefix=.merged- Makefile
|
||||||
|
----------------
|
||||||
|
+
|
||||||
|
This will check out the currently cached copy of `Makefile`
|
||||||
|
into the file `.merged-Makefile`.
|
||||||
|
|
||||||
git-checkout-index --prefix=.merged- Makefile
|
|
||||||
|
|
||||||
to check out the currently cached copy of `Makefile` into the file
|
|
||||||
`.merged-Makefile`
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org>
|
Written by Linus Torvalds <torvalds@osdl.org>
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
--------------
|
--------------
|
||||||
Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
|
Documentation by David Greaves,
|
||||||
|
Junio C Hamano and the git-list <git@vger.kernel.org>.
|
||||||
|
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
---
|
---
|
||||||
|
@ -50,10 +50,14 @@ the `Makefile` to two revisions back, deletes hello.c by
|
|||||||
mistake, and gets it back from the index.
|
mistake, and gets it back from the index.
|
||||||
|
|
||||||
------------
|
------------
|
||||||
$ git checkout master
|
$ git checkout master <1>
|
||||||
$ git checkout master~2 Makefile
|
$ git checkout master~2 Makefile <2>
|
||||||
$ rm -f hello.c
|
$ rm -f hello.c
|
||||||
$ git checkout hello.c
|
$ git checkout hello.c <3>
|
||||||
|
|
||||||
|
<1> switch branch
|
||||||
|
<2> take out a file out of other commit
|
||||||
|
<3> or "git checkout -- hello.c", as in the next example.
|
||||||
------------
|
------------
|
||||||
|
|
||||||
If you have an unfortunate branch that is named `hello.c`, the
|
If you have an unfortunate branch that is named `hello.c`, the
|
||||||
|
@ -7,7 +7,7 @@ git-cherry-pick - Apply the change introduced by an existing commit.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-cherry-pick' [-n] [-r] <commit>
|
'git-cherry-pick' [--edit] [-n] [-r] <commit>
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -20,15 +20,19 @@ OPTIONS
|
|||||||
<commit>::
|
<commit>::
|
||||||
Commit to cherry-pick.
|
Commit to cherry-pick.
|
||||||
|
|
||||||
-r::
|
-e|--edit::
|
||||||
|
With this option, `git-cherry-pick` will let you edit the commit
|
||||||
|
message prior committing.
|
||||||
|
|
||||||
|
-r|--replay::
|
||||||
Usually the command appends which commit was
|
Usually the command appends which commit was
|
||||||
cherry-picked after the original commit message when
|
cherry-picked after the original commit message when
|
||||||
making a commit. This option, '--replay', causes it to
|
making a commit. This option, '--replay', causes it to
|
||||||
use the original commit message intact. This is useful
|
use the original commit message intact. This is useful
|
||||||
when you are reordering the patches in your private tree
|
when you are reordering the patches in your private tree
|
||||||
before publishing, and is used by 'git rebase'.
|
before publishing.
|
||||||
|
|
||||||
-n::
|
-n|--no-commit::
|
||||||
Usually the command automatically creates a commit with
|
Usually the command automatically creates a commit with
|
||||||
a commit log message stating which commit was
|
a commit log message stating which commit was
|
||||||
cherry-picked. This flag applies the change necessary
|
cherry-picked. This flag applies the change necessary
|
||||||
|
@ -43,7 +43,11 @@ OPTIONS
|
|||||||
The heads to update. This is relative to $GIT_DIR
|
The heads to update. This is relative to $GIT_DIR
|
||||||
(e.g. "HEAD", "refs/heads/master"). When unspecified,
|
(e.g. "HEAD", "refs/heads/master"). When unspecified,
|
||||||
all heads are updated to match the remote repository.
|
all heads are updated to match the remote repository.
|
||||||
|
+
|
||||||
|
Usually all the refs from existing repository are stored
|
||||||
|
under the same name in the new repository. Giving explicit
|
||||||
|
<head> arguments instead writes the object names and refs to
|
||||||
|
the standard output, just like get-fetch-pack does.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -74,10 +74,31 @@ OPTIONS
|
|||||||
for "host.xz:foo/.git"). Cloning into an existing directory
|
for "host.xz:foo/.git"). Cloning into an existing directory
|
||||||
is not allowed.
|
is not allowed.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
Clone from upstream::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6
|
||||||
|
$ cd my2.6
|
||||||
|
$ make
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Make a local clone that borrows from the current directory, without checking things out::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git clone -l -s -n . ../copy
|
||||||
|
$ cd copy
|
||||||
|
$ git show-branch
|
||||||
|
------------
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org>
|
Written by Linus Torvalds <torvalds@osdl.org>
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
--------------
|
--------------
|
||||||
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
||||||
|
@ -8,7 +8,7 @@ git-commit-tree - Creates a new commit object
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-commit-tree' <tree> [-p <parent commit>]\ < changelog
|
'git-commit-tree' <tree> [-p <parent commit>]\* < changelog
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -26,8 +26,9 @@ to get there.
|
|||||||
|
|
||||||
Normally a commit would identify a new "HEAD" state, and while git
|
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
|
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
|
tend to just write the result to the file that is pointed at by
|
||||||
always see what the last committed state was.
|
`.git/HEAD`, so that we can always see what the last committed
|
||||||
|
state was.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
@ -7,7 +7,7 @@ git-commit - Record your changes
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg>] [-e] <file>...
|
'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg>] [-e] [--] <file>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -22,7 +22,7 @@ information.
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
-a::
|
-a|--all::
|
||||||
Update all paths in the index file.
|
Update all paths in the index file.
|
||||||
|
|
||||||
-c or -C <commit>::
|
-c or -C <commit>::
|
||||||
@ -39,27 +39,37 @@ OPTIONS
|
|||||||
-m <msg>::
|
-m <msg>::
|
||||||
Use the given <msg> as the commit message.
|
Use the given <msg> as the commit message.
|
||||||
|
|
||||||
-s::
|
-s|--signoff::
|
||||||
Add Signed-off-by line at the end of the commit message.
|
Add Signed-off-by line at the end of the commit message.
|
||||||
|
|
||||||
-v::
|
-v|--verify::
|
||||||
Look for suspicious lines the commit introduces, and
|
Look for suspicious lines the commit introduces, and
|
||||||
abort committing if there is one. The definition of
|
abort committing if there is one. The definition of
|
||||||
'suspicious lines' is currently the lines that has
|
'suspicious lines' is currently the lines that has
|
||||||
trailing whitespaces, and the lines whose indentation
|
trailing whitespaces, and the lines whose indentation
|
||||||
has a SP character immediately followed by a TAB
|
has a SP character immediately followed by a TAB
|
||||||
character.
|
character. This is the default.
|
||||||
|
|
||||||
-e::
|
-n|--no-verify::
|
||||||
|
The opposite of `--verify`.
|
||||||
|
|
||||||
|
-e|--edit::
|
||||||
The message taken from file with `-F`, command line with
|
The message taken from file with `-F`, command line with
|
||||||
`-m`, and from file with `-C` are usually used as the
|
`-m`, and from file with `-C` are usually used as the
|
||||||
commit log message unmodified. This option lets you
|
commit log message unmodified. This option lets you
|
||||||
further edit the message taken from these sources.
|
further edit the message taken from these sources.
|
||||||
|
|
||||||
|
--::
|
||||||
|
Do not interpret any more arguments as options.
|
||||||
|
|
||||||
<file>...::
|
<file>...::
|
||||||
Update specified paths in the index file before committing.
|
Update specified paths in the index file before committing.
|
||||||
|
|
||||||
|
|
||||||
|
If you make a commit and then found a mistake immediately after
|
||||||
|
that, you can recover from it with gitlink:git-reset[1].
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||||
|
@ -8,7 +8,7 @@ git-cvsexportcommit - Export a commit to a CVS checkout
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
git-cvsapplycommmit.perl
|
git-cvsexportcommmit.perl
|
||||||
[ -h ] [ -v ] [ -c ] [ -p ] [PARENTCOMMIT] COMMITID
|
[ -h ] [ -v ] [ -c ] [ -p ] [PARENTCOMMIT] COMMITID
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ the old cvs2git tool.
|
|||||||
+
|
+
|
||||||
If you need to pass multiple options, separate them with a comma.
|
If you need to pass multiple options, separate them with a comma.
|
||||||
|
|
||||||
-P:: <cvsps-output-file>
|
-P <cvsps-output-file>::
|
||||||
Instead of calling cvsps, read the provided cvsps output file. Useful
|
Instead of calling cvsps, read the provided cvsps output file. Useful
|
||||||
for debugging or when cvsps is being handled outside cvsimport.
|
for debugging or when cvsps is being handled outside cvsimport.
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ git-daemon - A really simple server for git repositories.
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
|
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
|
||||||
[--timeout=n] [--init-timeout=n] [directory...]
|
[--timeout=n] [--init-timeout=n] [--strict-paths] [directory...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -29,13 +29,19 @@ This is ideally suited for read-only updates, ie pulling from git repositories.
|
|||||||
|
|
||||||
OPTIONS
|
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::
|
--export-all::
|
||||||
Allow pulling from all directories that look like GIT repositories
|
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.
|
do not have the 'git-daemon-export-ok' file.
|
||||||
|
|
||||||
--inetd::
|
--inetd::
|
||||||
Have the server run as an inetd service.
|
Have the server run as an inetd service. Implies --syslog.
|
||||||
|
|
||||||
--port::
|
--port::
|
||||||
Listen on an alternative port.
|
Listen on an alternative port.
|
||||||
@ -57,9 +63,15 @@ OPTIONS
|
|||||||
--verbose::
|
--verbose::
|
||||||
Log details about the incoming connections and requested files.
|
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
|
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
|
Documentation
|
||||||
--------------
|
--------------
|
||||||
|
@ -21,6 +21,15 @@ OPTIONS
|
|||||||
-------
|
-------
|
||||||
include::diff-options.txt[]
|
include::diff-options.txt[]
|
||||||
|
|
||||||
|
-1 -2 -3 or --base --ours --theirs, and -0::
|
||||||
|
Diff against the "base" version, "our branch" or "their
|
||||||
|
branch" respectively. With these options, diffs for
|
||||||
|
merged entries are not shown.
|
||||||
|
+
|
||||||
|
The default is to diff against our branch (-2) and the
|
||||||
|
cleanly resolved paths. The option -0 can be given to
|
||||||
|
omit diff output for unmerged entries and just show "Unmerged".
|
||||||
|
|
||||||
-q::
|
-q::
|
||||||
Remain silent even on nonexisting files
|
Remain silent even on nonexisting files
|
||||||
|
|
||||||
|
@ -57,14 +57,14 @@ 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
|
*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
|
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
|
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.
|
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
|
"git-diff-files" wouldn't show anything at all, since the index file
|
||||||
matches my working directory. But doing a "git-diff-index" does:
|
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 commit.c
|
||||||
+100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 git-commit.c
|
+100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 git-commit.c
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ 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
|
have not actually done a "git-update-index" on it yet - there is no
|
||||||
"object" associated with the new state, and you get:
|
"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
|
*100644->100664 blob 7476bb......->000000...... kernel/sched.c
|
||||||
|
|
||||||
ie it shows that the tree has changed, and that `kernel/sched.c` has is
|
ie it shows that the tree has changed, and that `kernel/sched.c` has is
|
||||||
|
@ -17,14 +17,16 @@ ent and the index file, or the index file and the working tree.
|
|||||||
The combination of what is compared with what is determined by
|
The combination of what is compared with what is determined by
|
||||||
the number of ents given to the command.
|
the number of ents given to the command.
|
||||||
|
|
||||||
`----------------`--------`-----------------------------`------------------
|
* When no <ent> is given, the working tree and the index
|
||||||
Number of ents Options What's Compared Underlying command
|
file is compared, using `git-diff-files`.
|
||||||
---------------------------------------------------------------------------
|
|
||||||
0 - index file and working tree git-diff-files
|
* When one <ent> is given, the working tree and the named
|
||||||
1 --cached ent and index file git-diff-index
|
tree is compared, using `git-diff-index`. The option
|
||||||
1 - ent and working tree git-diff-index
|
`--cached` can be given to compare the index file and
|
||||||
2 - two ents git-diff-tree
|
the named tree.
|
||||||
---------------------------------------------------------------------------
|
|
||||||
|
* When two <ent>s are given, these two trees are compared
|
||||||
|
using `git-diff-tree`.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
@ -38,6 +40,68 @@ OPTIONS
|
|||||||
commands.
|
commands.
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
|
||||||
|
Various ways to check your working tree::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git diff <1>
|
||||||
|
$ git diff --cached <2>
|
||||||
|
$ git diff HEAD <3>
|
||||||
|
|
||||||
|
<1> changes in the working tree since your last git-update-index.
|
||||||
|
<2> changes between the index and your last commit; what you
|
||||||
|
would be committing if you run "git commit" without "-a" option.
|
||||||
|
<3> changes in the working tree since your last commit; what you
|
||||||
|
would be committing if you run "git commit -a"
|
||||||
|
------------
|
||||||
|
|
||||||
|
Comparing with arbitrary commits::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git diff test <1>
|
||||||
|
$ git diff HEAD -- ./test <2>
|
||||||
|
$ git diff HEAD^ HEAD <3>
|
||||||
|
|
||||||
|
<1> instead of using the tip of the current branch, compare with the
|
||||||
|
tip of "test" branch.
|
||||||
|
<2> instead of comparing with the tip of "test" branch, compare with
|
||||||
|
the tip of the curren branch, but limit the comparison to the
|
||||||
|
file "test".
|
||||||
|
<3> compare the version before the last commit and the last commit.
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Limiting the diff output::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git diff --diff-filter=MRC <1>
|
||||||
|
$ git diff --name-status -r <2>
|
||||||
|
$ git diff arch/i386 include/asm-i386 <3>
|
||||||
|
|
||||||
|
<1> show only modification, rename and copy, but not addition
|
||||||
|
nor deletion.
|
||||||
|
<2> show only names and the nature of change, but not actual
|
||||||
|
diff output. --name-status disables usual patch generation
|
||||||
|
which in turn also disables recursive behaviour, so without -r
|
||||||
|
you would only see the directory name if there is a change in a
|
||||||
|
file in a subdirectory.
|
||||||
|
<3> limit diff output to named subtrees.
|
||||||
|
------------
|
||||||
|
|
||||||
|
Munging the diff output::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git diff --find-copies-harder -B -C <1>
|
||||||
|
$ git diff -R <2>
|
||||||
|
|
||||||
|
<1> spend extra cycles to find renames, copies and complete
|
||||||
|
rewrites (very expensive).
|
||||||
|
<2> output diff in reverse.
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org>
|
Written by Linus Torvalds <torvalds@osdl.org>
|
||||||
|
@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
git-fetch-pack [-q] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
|
git-fetch-pack [-q] [-k] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -29,6 +29,11 @@ OPTIONS
|
|||||||
Pass '-q' flag to 'git-unpack-objects'; this makes the
|
Pass '-q' flag to 'git-unpack-objects'; this makes the
|
||||||
cloning process less verbose.
|
cloning process less verbose.
|
||||||
|
|
||||||
|
-k::
|
||||||
|
Do not invoke 'git-unpack-objects' on received data, but
|
||||||
|
create a single packfile out of it instead, and store it
|
||||||
|
in the object database.
|
||||||
|
|
||||||
--exec=<git-upload-pack>::
|
--exec=<git-upload-pack>::
|
||||||
Use this to specify the path to 'git-upload-pack' on the
|
Use this to specify the path to 'git-upload-pack' on the
|
||||||
remote side, if is not found on your $PATH.
|
remote side, if is not found on your $PATH.
|
||||||
|
@ -18,7 +18,7 @@ the objects necessary to complete them.
|
|||||||
|
|
||||||
The ref names and their object names of fetched refs are stored
|
The ref names and their object names of fetched refs are stored
|
||||||
in `.git/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".
|
operation done by "git merge".
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
|
@ -8,7 +8,7 @@ git-format-patch - Prepare patches for e-mail submission.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-format-patch' [-n][-o <dir>|--stdout][-k][--mbox][--diff-options] <his> [<mine>]
|
'git-format-patch' [-n | -k] [-o <dir> | --stdout] [-s] [-c] [--mbox] [--diff-options] <his> [<mine>]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -32,23 +32,34 @@ processing with applymbox.
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
-o <dir>::
|
-o|--output-directory <dir>::
|
||||||
Use <dir> to store the resulting files, instead of the
|
Use <dir> to store the resulting files, instead of the
|
||||||
current working directory.
|
current working directory.
|
||||||
|
|
||||||
-n::
|
-n|--numbered::
|
||||||
Name output in '[PATCH n/m]' format.
|
Name output in '[PATCH n/m]' format.
|
||||||
|
|
||||||
-k::
|
-k|--keep-subject::
|
||||||
Do not strip/add '[PATCH]' from the first line of the
|
Do not strip/add '[PATCH]' from the first line of the
|
||||||
commit log message.
|
commit log message.
|
||||||
|
|
||||||
--author, --date::
|
-a|--author, -d|--date::
|
||||||
Output From: and Date: headers for commits made by
|
Output From: and Date: headers for commits made by
|
||||||
yourself as well. Usually these are output only for
|
yourself as well. Usually these are output only for
|
||||||
commits made by people other than yourself.
|
commits made by people other than yourself.
|
||||||
|
|
||||||
--mbox::
|
-s|--signoff::
|
||||||
|
Add `Signed-off-by:` line to the commit message, using
|
||||||
|
the committer identity of yourself.
|
||||||
|
|
||||||
|
-c|--check::
|
||||||
|
Display suspicious lines in the patch. The definition
|
||||||
|
of 'suspicious lines' is currently the lines that has
|
||||||
|
trailing whitespaces, and the lines whose indentation
|
||||||
|
has a SP character immediately followed by a TAB
|
||||||
|
character.
|
||||||
|
|
||||||
|
-m|--mbox::
|
||||||
Format the output files for closer to mbox format by
|
Format the output files for closer to mbox format by
|
||||||
adding a phony Unix "From " line, so they can be
|
adding a phony Unix "From " line, so they can be
|
||||||
concatenated together and fed to `git-applymbox`.
|
concatenated together and fed to `git-applymbox`.
|
||||||
@ -73,6 +84,15 @@ git-format-patch origin::
|
|||||||
pulled from origin the last time in a patch form for
|
pulled from origin the last time in a patch form for
|
||||||
e-mail submission.
|
e-mail submission.
|
||||||
|
|
||||||
|
git-format-patch -M -B origin::
|
||||||
|
The same as the previous one, except detect and handle
|
||||||
|
renames and complete rewrites intelligently to produce
|
||||||
|
renaming patch. A renaming patch reduces the amount of
|
||||||
|
text output, and generally makes it easier to review
|
||||||
|
it. Note that the "patch" program does not understand
|
||||||
|
renaming patch well, so use it only when you know the
|
||||||
|
recipient uses git to apply your patch.
|
||||||
|
|
||||||
|
|
||||||
See Also
|
See Also
|
||||||
--------
|
--------
|
||||||
|
@ -68,7 +68,7 @@ that aren't readable from any of the specified head nodes.
|
|||||||
|
|
||||||
So for example
|
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
|
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
|
extra validity tests to be added (make sure that tree objects are
|
||||||
|
@ -8,7 +8,7 @@ git-hash-object - Computes object ID and optionally creates a blob from a file.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-hash-object' [-t <type>] [-w] <any-file-on-the-filesystem>
|
'git-hash-object' [-t <type>] [-w] [--stdin] [--] <file>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -29,6 +29,9 @@ OPTIONS
|
|||||||
-w::
|
-w::
|
||||||
Actually write the object into the object database.
|
Actually write the object into the object database.
|
||||||
|
|
||||||
|
--stdin::
|
||||||
|
Read the object from standard input instead of from a file.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Junio C Hamano <junkio@cox.net>
|
Written by Junio C Hamano <junkio@cox.net>
|
||||||
|
@ -14,6 +14,12 @@ DESCRIPTION
|
|||||||
-----------
|
-----------
|
||||||
Downloads a remote git repository via HTTP.
|
Downloads a remote git repository via HTTP.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
commit-id::
|
||||||
|
Either the hash or the filename under [URL]/refs/ to
|
||||||
|
pull.
|
||||||
|
|
||||||
-c::
|
-c::
|
||||||
Get the commit objects.
|
Get the commit objects.
|
||||||
-t::
|
-t::
|
||||||
|
@ -8,7 +8,14 @@ git-init-db - Creates an empty git repository
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-init-db'
|
'git-init-db' [--template=<template_directory>]
|
||||||
|
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
--template=<template_directory>::
|
||||||
|
Provide the directory in from which templates will be used.
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -16,14 +23,29 @@ This simply creates an empty git repository - basically a `.git` directory
|
|||||||
and `.git/object/??/`, `.git/refs/heads` and `.git/refs/tags` directories,
|
and `.git/object/??/`, `.git/refs/heads` and `.git/refs/tags` directories,
|
||||||
and links `.git/HEAD` symbolically to `.git/refs/heads/master`.
|
and links `.git/HEAD` symbolically to `.git/refs/heads/master`.
|
||||||
|
|
||||||
If the 'GIT_DIR' environment variable is set then it specifies a path
|
If the `$GIT_DIR` environment variable is set then it specifies a path
|
||||||
to use instead of `./.git` for the base of the repository.
|
to use instead of `./.git` for the base of the repository.
|
||||||
|
|
||||||
If the object storage directory is specified via the 'GIT_OBJECT_DIRECTORY'
|
If the object storage directory is specified via the `$GIT_OBJECT_DIRECTORY`
|
||||||
environment variable then the sha1 directories are created underneath -
|
environment variable then the sha1 directories are created underneath -
|
||||||
otherwise the default `$GIT_DIR/objects` directory is used.
|
otherwise the default `$GIT_DIR/objects` directory is used.
|
||||||
|
|
||||||
"git-init-db" won't hurt an existing repository.
|
`git-init-db` won't hurt an existing repository.
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
|
||||||
|
Start a new git repository for an existing code base::
|
||||||
|
+
|
||||||
|
----------------
|
||||||
|
$ cd /path/to/my/codebase
|
||||||
|
$ git-init-db <1>
|
||||||
|
$ git-add . <2>
|
||||||
|
|
||||||
|
<1> prepare /path/to/my/codebase/.git directory
|
||||||
|
<2> add all existing file to the index
|
||||||
|
----------------
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
|
@ -20,7 +20,7 @@ This manual page describes only the most frequently used options.
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
--pretty=<format>:
|
--pretty=<format>::
|
||||||
Controls the way the commit log is formatted.
|
Controls the way the commit log is formatted.
|
||||||
|
|
||||||
--max-count=<n>::
|
--max-count=<n>::
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
git-lost+found(1)
|
git-lost-found(1)
|
||||||
=================
|
=================
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
----
|
----
|
||||||
git-lost+found - Recover lost refs that luckily have not yet been pruned.
|
git-lost-found - Recover lost refs that luckily have not yet been pruned.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-lost+found'
|
'git-lost-found'
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -31,7 +31,7 @@ The ref to your tag is overwritten, but until you run 'git
|
|||||||
prune', it is still there.
|
prune', it is still there.
|
||||||
|
|
||||||
------------
|
------------
|
||||||
$ git lost+found
|
$ git lost-found
|
||||||
[1ef2b196d909eed523d4f3c9bf54b78cdd6843c6] GIT 0.99.9c
|
[1ef2b196d909eed523d4f3c9bf54b78cdd6843c6] GIT 0.99.9c
|
||||||
...
|
...
|
||||||
------------
|
------------
|
@ -17,7 +17,7 @@ Displays the references other repository has.
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
--heads --tags::
|
-h|--heads, -t|--tags::
|
||||||
Limit to only refs/heads and refs/tags, respectively.
|
Limit to only refs/heads and refs/tags, respectively.
|
||||||
These options are _not_ mutually exclusive; when given
|
These options are _not_ mutually exclusive; when given
|
||||||
both, references stored in refs/heads and refs/tags are
|
both, references stored in refs/heads and refs/tags are
|
||||||
|
@ -8,12 +8,15 @@ git-ls-tree - Lists the contents of a tree object.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-ls-tree' [-d] [-r] [-z] <tree-ish> [paths...]
|
'git-ls-tree' [-d] [-r] [-t] [-z] [--name-only] [--name-status] <tree-ish> [paths...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Lists the contents of a tree object, like what "/bin/ls -a" does
|
Lists the contents of a given tree object, like what "/bin/ls -a" does
|
||||||
in the current working directory.
|
in the current working directory. Note that the usage is subtly different,
|
||||||
|
though - 'paths' denote just a list of patterns to match, e.g. so specifying
|
||||||
|
directory name (without '-r') will behave differently, and order of the
|
||||||
|
arguments does not matter.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
@ -21,36 +24,48 @@ OPTIONS
|
|||||||
Id of a tree-ish.
|
Id of a tree-ish.
|
||||||
|
|
||||||
-d::
|
-d::
|
||||||
show only the named tree entry itself, not its children
|
Show only the named tree entry itself, not its children.
|
||||||
|
|
||||||
-r::
|
-r::
|
||||||
recurse into sub-trees
|
Recurse into sub-trees.
|
||||||
|
|
||||||
|
-t::
|
||||||
|
Show tree entries even when going to recurse them. Has no effect
|
||||||
|
if '-r' was not passed. '-d' implies '-t'.
|
||||||
|
|
||||||
-z::
|
-z::
|
||||||
\0 line termination on output
|
\0 line termination on output.
|
||||||
|
|
||||||
|
--name-only::
|
||||||
|
--name-status::
|
||||||
|
List only filenames (instead of the "long" output), one per line.
|
||||||
|
|
||||||
paths::
|
paths::
|
||||||
When paths are given, show them. Otherwise implicitly
|
When paths are given, show them (note that this isn't really raw
|
||||||
uses the root level of the tree as the sole path argument.
|
pathnames, but rather a list of patterns to match). Otherwise
|
||||||
|
implicitly uses the root level of the tree as the sole path argument.
|
||||||
|
|
||||||
|
|
||||||
Output Format
|
Output Format
|
||||||
-------------
|
-------------
|
||||||
<mode> SP <type> SP <object> TAB <file>
|
<mode> SP <type> SP <object> TAB <file>
|
||||||
|
|
||||||
When `-z` option is not used, TAB, LF, and backslash characters
|
When the `-z` option is not used, TAB, LF, and backslash characters
|
||||||
in pathnames are represented as `\t`, `\n`, and `\\`,
|
in pathnames are represented as `\t`, `\n`, and `\\`, respectively.
|
||||||
respectively.
|
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org>
|
Written by Petr Baudis <pasky@suse.cz>
|
||||||
Completely rewritten from scratch by Junio C Hamano <junkio@cox.net>
|
Completely rewritten from scratch by Junio C Hamano <junkio@cox.net>,
|
||||||
|
another major rewrite by Linus Torvalds <torvalds@osdl.org>
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
--------------
|
--------------
|
||||||
Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
|
Documentation by David Greaves, Junio C Hamano and the git-list
|
||||||
|
<git@vger.kernel.org>.
|
||||||
|
|
||||||
|
This manual page is a stub. You can help the git documentation by expanding it.
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
---
|
---
|
||||||
|
@ -8,7 +8,7 @@ git-mailinfo - Extracts patch from a single e-mail message.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-mailinfo' [-k] [-u] <msg> <patch>
|
'git-mailinfo' [-k] [-u | --encoding=<encoding>] <msg> <patch>
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -37,10 +37,17 @@ OPTIONS
|
|||||||
author email are taken from the e-mail without any
|
author email are taken from the e-mail without any
|
||||||
charset conversion, after minimally decoding MIME
|
charset conversion, after minimally decoding MIME
|
||||||
transfer encoding. This flag causes the resulting
|
transfer encoding. This flag causes the resulting
|
||||||
commit to be encoded in utf-8 by transliterating them.
|
commit to be encoded in the encoding specified by
|
||||||
|
i18n.commitencoding configuration (defaults to utf-8) by
|
||||||
|
transliterating them.
|
||||||
Note that the patch is always used as is without charset
|
Note that the patch is always used as is without charset
|
||||||
conversion, even with this flag.
|
conversion, even with this flag.
|
||||||
|
|
||||||
|
--encoding=<encoding>::
|
||||||
|
Similar to -u but if the local convention is different
|
||||||
|
from what is specified by i18n.commitencoding, this flag
|
||||||
|
can be used to override it.
|
||||||
|
|
||||||
<msg>::
|
<msg>::
|
||||||
The commit log message extracted from e-mail, usually
|
The commit log message extracted from e-mail, usually
|
||||||
except the title line which comes from e-mail Subject.
|
except the title line which comes from e-mail Subject.
|
||||||
|
@ -7,7 +7,7 @@ git-mailsplit - Totally braindamaged mbox splitter program.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-mailsplit' [-d<prec>] [<mbox>] <directory>
|
'git-mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -23,11 +23,18 @@ OPTIONS
|
|||||||
<directory>::
|
<directory>::
|
||||||
Directory in which to place the individual messages.
|
Directory in which to place the individual messages.
|
||||||
|
|
||||||
|
-b::
|
||||||
|
If any file doesn't begin with a From line, assume it is a
|
||||||
|
single mail message instead of signalling error.
|
||||||
|
|
||||||
-d<prec>::
|
-d<prec>::
|
||||||
Instead of the default 4 digits with leading zeros,
|
Instead of the default 4 digits with leading zeros,
|
||||||
different precision can be specified for the generated
|
different precision can be specified for the generated
|
||||||
filenames.
|
filenames.
|
||||||
|
|
||||||
|
-f<nn>::
|
||||||
|
Skip the first <nn> numbers, for example if -f3 is specified,
|
||||||
|
start the numbering with 0004.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -20,7 +20,7 @@ files are passed as arguments 5, 6 and 7.
|
|||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
--::
|
--::
|
||||||
Interpret all following arguments as filenames.
|
Do not interpret any more arguments as options.
|
||||||
|
|
||||||
-a::
|
-a::
|
||||||
Run merge against all files in the index that need merging.
|
Run merge against all files in the index that need merging.
|
||||||
|
@ -37,6 +37,108 @@ include::merge-options.txt[]
|
|||||||
include::merge-strategies.txt[]
|
include::merge-strategies.txt[]
|
||||||
|
|
||||||
|
|
||||||
|
If you tried a merge which resulted in a complex conflicts and
|
||||||
|
would want to start over, you can recover with
|
||||||
|
gitlink:git-reset[1].
|
||||||
|
|
||||||
|
|
||||||
|
HOW MERGE WORKS
|
||||||
|
---------------
|
||||||
|
|
||||||
|
A merge is always between the current `HEAD` and one or more
|
||||||
|
remote branch heads, and the index file must exactly match the
|
||||||
|
tree of `HEAD` commit (i.e. the contents of the last commit) when
|
||||||
|
it happens. In other words, `git-diff --cached HEAD` must
|
||||||
|
report no changes.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
This is a bit of lie. In certain special cases, your index are
|
||||||
|
allowed to be different from the tree of `HEAD` commit. The most
|
||||||
|
notable case is when your `HEAD` commit is already ahead of what
|
||||||
|
is being merged, in which case your index can have arbitrary
|
||||||
|
difference from your `HEAD` commit. Otherwise, your index entries
|
||||||
|
are allowed have differences from your `HEAD` commit that match
|
||||||
|
the result of trivial merge (e.g. you received the same patch
|
||||||
|
from external source to produce the same result as what you are
|
||||||
|
merging). For example, if a path did not exist in the common
|
||||||
|
ancestor and your head commit but exists in the tree you are
|
||||||
|
merging into your repository, and if you already happen to have
|
||||||
|
that path exactly in your index, the merge does not have to
|
||||||
|
fail.
|
||||||
|
|
||||||
|
Otherwise, merge will refuse to do any harm to your repository
|
||||||
|
(that is, it may fetch the objects from remote, and it may even
|
||||||
|
update the local branch used to keep track of the remote branch
|
||||||
|
with `git pull remote rbranch:lbranch`, but your working tree,
|
||||||
|
`.git/HEAD` pointer and index file are left intact).
|
||||||
|
|
||||||
|
You may have local modifications in the working tree files. In
|
||||||
|
other words, `git-diff` is allowed to report changes.
|
||||||
|
However, the merge uses your working tree as the working area,
|
||||||
|
and in order to prevent the merge operation from losing such
|
||||||
|
changes, it makes sure that they do not interfere with the
|
||||||
|
merge. Those complex tables in read-tree documentation define
|
||||||
|
what it means for a path to "interfere with the merge". And if
|
||||||
|
your local modifications interfere with the merge, again, it
|
||||||
|
stops before touching anything.
|
||||||
|
|
||||||
|
So in the above two "failed merge" case, you do not have to
|
||||||
|
worry about lossage of data --- you simply were not ready to do
|
||||||
|
a merge, so no merge happened at all. You may want to finish
|
||||||
|
whatever you were in the middle of doing, and retry the same
|
||||||
|
pull after you are done and ready.
|
||||||
|
|
||||||
|
When things cleanly merge, these things happen:
|
||||||
|
|
||||||
|
1. the results are updated both in the index file and in your
|
||||||
|
working tree,
|
||||||
|
2. index file is written out as a tree,
|
||||||
|
3. the tree gets committed, and
|
||||||
|
4. the `HEAD` pointer gets advanced.
|
||||||
|
|
||||||
|
Because of 2., we require that the original state of the index
|
||||||
|
file to match exactly the current `HEAD` commit; otherwise we
|
||||||
|
will write out your local changes already registered in your
|
||||||
|
index file along with the merge result, which is not good.
|
||||||
|
Because 1. involves only the paths different between your
|
||||||
|
branch and the remote branch you are pulling from during the
|
||||||
|
merge (which is typically a fraction of the whole tree), you can
|
||||||
|
have local modifications in your working tree as long as they do
|
||||||
|
not overlap with what the merge updates.
|
||||||
|
|
||||||
|
When there are conflicts, these things happen:
|
||||||
|
|
||||||
|
1. `HEAD` stays the same.
|
||||||
|
|
||||||
|
2. Cleanly merged paths are updated both in the index file and
|
||||||
|
in your working tree.
|
||||||
|
|
||||||
|
3. For conflicting paths, the index file records up to three
|
||||||
|
versions; stage1 stores the version from the common ancestor,
|
||||||
|
stage2 from `HEAD`, and stage3 from the remote branch (you
|
||||||
|
can inspect the stages with `git-ls-files -u`). The working
|
||||||
|
tree files have the result of "merge" program; i.e. 3-way
|
||||||
|
merge result with familiar conflict markers `<<< === >>>`.
|
||||||
|
|
||||||
|
4. No other changes are done. In particular, the local
|
||||||
|
modifications you had before you started merge will stay the
|
||||||
|
same and the index entries for them stay as they were,
|
||||||
|
i.e. matching `HEAD`.
|
||||||
|
|
||||||
|
After seeing a conflict, you can do two things:
|
||||||
|
|
||||||
|
* Decide not to merge. The only clean-up you need are to reset
|
||||||
|
the index file to the `HEAD` commit to reverse 2. and to clean
|
||||||
|
up working tree changes made by 2. and 3.; `git-reset` can
|
||||||
|
be used for this.
|
||||||
|
|
||||||
|
* Resolve the conflicts. `git-diff` would report only the
|
||||||
|
conflicting paths because of the above 2. and 3.. Edit the
|
||||||
|
working tree files into a desirable shape, `git-update-index`
|
||||||
|
them, to make the index file contain what the merge result
|
||||||
|
should be, and run `git-commit` to commit the result.
|
||||||
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
gitlink:git-fmt-merge-msg[1], gitlink:git-pull[1]
|
gitlink:git-fmt-merge-msg[1], gitlink:git-pull[1]
|
||||||
|
@ -8,14 +8,17 @@ git-mv - Script used to move or rename a file, directory or symlink.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-mv' [-f] [-n] <source> <destination>
|
'git-mv' <options>... <args>...
|
||||||
'git-mv' [-f] [-k] [-n] <source> ... <destination directory>
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
This script is used to move or rename a file, directory or symlink.
|
This script is used to move or rename a file, directory or symlink.
|
||||||
|
|
||||||
|
git-mv [-f] [-n] <source> <destination>
|
||||||
|
git-mv [-f] [-n] [-k] <source> ... <destination directory>
|
||||||
|
|
||||||
In the first form, it renames <source>, which must exist and be either
|
In the first form, it renames <source>, which must exist and be either
|
||||||
a file, symlink or directory, to <destination>, which must not exist.
|
a file, symlink or directory, to <destination>.
|
||||||
In the second form, the last argument has to be an existing
|
In the second form, the last argument has to be an existing
|
||||||
directory; the given sources will be moved into this directory.
|
directory; the given sources will be moved into this directory.
|
||||||
|
|
||||||
@ -25,7 +28,7 @@ committed.
|
|||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
-f::
|
-f::
|
||||||
Force renaming or moving even targets exist
|
Force renaming or moving of a file even if the target exists
|
||||||
-k::
|
-k::
|
||||||
Skip move or rename actions which would lead to an error
|
Skip move or rename actions which would lead to an error
|
||||||
condition. An error happens when a source is neither existing nor
|
condition. An error happens when a source is neither existing nor
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
git-octopus(1)
|
|
||||||
==============
|
|
||||||
|
|
||||||
NAME
|
|
||||||
----
|
|
||||||
git-octopus - Merge more than two commits.
|
|
||||||
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
--------
|
|
||||||
'git-octopus'
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
-----------
|
|
||||||
After running 'git fetch', $GIT_DIR/FETCH_HEAD contains the
|
|
||||||
following information, one line per remote ref:
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
<object name> <ref name> from <repository>
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
Using this information, create and commit an Octopus merge on
|
|
||||||
top of the current HEAD.
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
@ -8,7 +8,7 @@ git-pack-objects - Create a packed archive of objects.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-pack-objects' [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list
|
'git-pack-objects' [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -70,6 +70,10 @@ base-name::
|
|||||||
that are packed and not in the local object store
|
that are packed and not in the local object store
|
||||||
(i.e. borrowed from an alternate).
|
(i.e. borrowed from an alternate).
|
||||||
|
|
||||||
|
--non-empty::
|
||||||
|
Only create a packed archive if it would contain at
|
||||||
|
least one object.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org>
|
Written by Linus Torvalds <torvalds@osdl.org>
|
||||||
|
@ -16,6 +16,14 @@ This program computes which packs in your repository
|
|||||||
are redundant. The output is suitable for piping to
|
are redundant. The output is suitable for piping to
|
||||||
'xargs rm' if you are in the root of the repository.
|
'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
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
@ -9,19 +9,28 @@ residing in a pack file.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-prune-packed'
|
'git-prune-packed' [-n]
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
This program search the GIT_OBJECT_DIR for all objects that currently exist in
|
This program search the `$GIT_OBJECT_DIR` for all objects that currently
|
||||||
a pack file as well as the independent object directories.
|
exist in a pack file as well as the independent object directories.
|
||||||
|
|
||||||
All such extra objects are removed.
|
All such extra objects are removed.
|
||||||
|
|
||||||
A pack is a collection of objects, individually compressed, with delta
|
A pack is a collection of objects, individually compressed, with delta
|
||||||
compression applied, stored in a single file, with an associated index file.
|
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.
|
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
|
Author
|
||||||
------
|
------
|
||||||
|
@ -8,15 +8,16 @@ git-prune - Prunes all unreachable objects from the object database
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-prune' [-n]
|
'git-prune' [-n] [--] [<head>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
This runs `git-fsck-objects --unreachable` using the heads
|
This runs `git-fsck-objects --unreachable` using all the refs
|
||||||
specified on the command line (or `$GIT_DIR/refs/heads/\*` and
|
available in `$GIT_DIR/refs`, optionally with additional set of
|
||||||
`$GIT_DIR/refs/tags/\*` if none is specified), and prunes all
|
objects specified on the command line, and prunes all
|
||||||
unreachable objects from the object database. In addition, it
|
objects unreachable from any of these head objects from the object database.
|
||||||
|
In addition, it
|
||||||
prunes the unpacked objects that are also found in packs by
|
prunes the unpacked objects that are also found in packs by
|
||||||
running `git prune-packed`.
|
running `git prune-packed`.
|
||||||
|
|
||||||
@ -27,6 +28,24 @@ OPTIONS
|
|||||||
Do not remove anything; just report what it would
|
Do not remove anything; just report what it would
|
||||||
remove.
|
remove.
|
||||||
|
|
||||||
|
--::
|
||||||
|
Do not interpret any more arguments as options.
|
||||||
|
|
||||||
|
<head>...::
|
||||||
|
In addition to objects
|
||||||
|
reachable from any of our references, keep objects
|
||||||
|
reachable from listed <head>s.
|
||||||
|
|
||||||
|
EXAMPLE
|
||||||
|
-------
|
||||||
|
|
||||||
|
To prune objects not used by your repository nor another that
|
||||||
|
borrows from your repository via its
|
||||||
|
`.git/objects/info/alternates`:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git prune $(cd ../another && $(git-rev-parse --all))
|
||||||
|
------------
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -104,6 +104,11 @@ merge the remote `origin` head into the current,
|
|||||||
local `master` branch.
|
local `master` branch.
|
||||||
|
|
||||||
|
|
||||||
|
If you tried a pull which resulted in a complex conflicts and
|
||||||
|
would want to start over, you can recover with
|
||||||
|
gitlink:git-reset[1].
|
||||||
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
gitlink:git-fetch[1], gitlink:git-merge[1]
|
gitlink:git-fetch[1], gitlink:git-merge[1]
|
||||||
|
@ -16,6 +16,10 @@ DESCRIPTION
|
|||||||
Updates remote refs using local refs, while sending objects
|
Updates remote refs using local refs, while sending objects
|
||||||
necessary to complete the given refs.
|
necessary to complete the given refs.
|
||||||
|
|
||||||
|
You can make "interesting" things to happen on the repository
|
||||||
|
every time you push into it, by setting up 'hooks' there. See
|
||||||
|
documentation for gitlink:git-receive-pack[1].
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
@ -31,6 +35,7 @@ include::pull-fetch-param.txt[]
|
|||||||
This flag disables the check. What this means is that the
|
This flag disables the check. What this means is that the
|
||||||
local repository can lose commits; use it with care.
|
local repository can lose commits; use it with care.
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Junio C Hamano <junkio@cox.net>
|
Written by Junio C Hamano <junkio@cox.net>
|
||||||
|
@ -8,27 +8,34 @@ git-read-tree - Reads tree information into the index
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-read-tree' (<tree-ish> | [-m [-u|-i]] <tree-ish1> [<tree-ish2> [<tree-ish3>]])
|
'git-read-tree' (<tree-ish> | [[-m | --reset] [-u | -i]] <tree-ish1> [<tree-ish2> [<tree-ish3>]])
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Reads the tree information given by <tree-ish> into the index,
|
Reads the tree information given by <tree-ish> into the index,
|
||||||
but does not actually *update* any of the files it "caches". (see:
|
but does not actually *update* any of the files it "caches". (see:
|
||||||
git-checkout-index)
|
gitlink:git-checkout-index[1])
|
||||||
|
|
||||||
Optionally, it can merge a tree into the index, 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
|
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
|
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.
|
the files in the work tree with the result of the merge.
|
||||||
|
|
||||||
Trivial merges are done by "git-read-tree" itself. Only conflicting paths
|
Trivial merges are done by `git-read-tree` itself. Only conflicting paths
|
||||||
will be in unmerged state when "git-read-tree" returns.
|
will be in unmerged state when `git-read-tree` returns.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
-m::
|
-m::
|
||||||
Perform a merge, not just a read.
|
Perform a merge, not just a read. The command will
|
||||||
|
refuse to run if your index file has unmerged entries,
|
||||||
|
indicating that you have not finished previous merge you
|
||||||
|
started.
|
||||||
|
|
||||||
|
--reset::
|
||||||
|
Same as -m, except that unmerged entries are discarded
|
||||||
|
instead of failing.
|
||||||
|
|
||||||
-u::
|
-u::
|
||||||
After a successful merge, update the files in the work
|
After a successful merge, update the files in the work
|
||||||
@ -43,14 +50,13 @@ OPTIONS
|
|||||||
trees that are not directly related to the current
|
trees that are not directly related to the current
|
||||||
working tree status into a temporary index file.
|
working tree status into a temporary index file.
|
||||||
|
|
||||||
|
|
||||||
<tree-ish#>::
|
<tree-ish#>::
|
||||||
The id of the tree object(s) to be read/merged.
|
The id of the tree object(s) to be read/merged.
|
||||||
|
|
||||||
|
|
||||||
Merging
|
Merging
|
||||||
-------
|
-------
|
||||||
If '-m' is specified, "git-read-tree" can perform 3 kinds of
|
If `-m` is specified, `git-read-tree` can perform 3 kinds of
|
||||||
merge, a single tree merge if only 1 tree is given, a
|
merge, a single tree merge if only 1 tree is given, a
|
||||||
fast-forward merge with 2 trees, or a 3-way merge if 3 trees are
|
fast-forward merge with 2 trees, or a 3-way merge if 3 trees are
|
||||||
provided.
|
provided.
|
||||||
@ -59,23 +65,23 @@ provided.
|
|||||||
Single Tree Merge
|
Single Tree Merge
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
If only 1 tree is specified, git-read-tree operates as if the user did not
|
If only 1 tree is specified, git-read-tree operates as if the user did not
|
||||||
specify '-m', except that if the original index 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
|
given pathname, and the contents of the path matches with the tree
|
||||||
being read, the stat info from the index is used. (In other words, the
|
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).
|
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
|
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
|
`git-checkout-index -f -u -a`, the `git-checkout-index` only checks out
|
||||||
the stuff that really changed.
|
the stuff that really changed.
|
||||||
|
|
||||||
This is used to avoid unnecessary false hits when "git-diff-files" is
|
This is used to avoid unnecessary false hits when `git-diff-files` is
|
||||||
run after git-read-tree.
|
run after `git-read-tree`.
|
||||||
|
|
||||||
|
|
||||||
Two Tree Merge
|
Two Tree Merge
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Typically, this is invoked as "git-read-tree -m $H $M", where $H
|
Typically, this is invoked as `git-read-tree -m $H $M`, where $H
|
||||||
is the head commit of the current repository, and $M is the head
|
is the head commit of the current repository, and $M is the head
|
||||||
of a foreign tree, which is simply ahead of $H (i.e. we are in a
|
of a foreign tree, which is simply ahead of $H (i.e. we are in a
|
||||||
fast forward situation).
|
fast forward situation).
|
||||||
@ -88,7 +94,7 @@ the following:
|
|||||||
|
|
||||||
2. The user wants to fast-forward to $M.
|
2. The user wants to fast-forward to $M.
|
||||||
|
|
||||||
In this case, the "git-read-tree -m $H $M" command makes sure
|
In this case, the `git-read-tree -m $H $M` command makes sure
|
||||||
that no local change is lost as the result of this "merge".
|
that no local change is lost as the result of this "merge".
|
||||||
Here are the "carry forward" rules:
|
Here are the "carry forward" rules:
|
||||||
|
|
||||||
@ -135,13 +141,13 @@ operating under the -u flag.
|
|||||||
|
|
||||||
When this form of git-read-tree returns successfully, you can
|
When this form of git-read-tree returns successfully, you can
|
||||||
see what "local changes" you made are carried forward by running
|
see what "local changes" you made are carried forward by running
|
||||||
"git-diff-index --cached $M". Note that this does not
|
`git-diff-index --cached $M`. Note that this does not
|
||||||
necessarily match "git-diff-index --cached $H" would have
|
necessarily match `git-diff-index --cached $H` would have
|
||||||
produced before such a two tree merge. This is because of cases
|
produced before such a two tree merge. This is because of cases
|
||||||
18 and 19 --- if you already had the changes in $M (e.g. maybe
|
18 and 19 --- if you already had the changes in $M (e.g. maybe
|
||||||
you picked it up via e-mail in a patch form), "git-diff-index
|
you picked it up via e-mail in a patch form), `git-diff-index
|
||||||
--cached $H" would have told you about the change before this
|
--cached $H` would have told you about the change before this
|
||||||
merge, but it would not show in "git-diff-index --cached $M"
|
merge, but it would not show in `git-diff-index --cached $M`
|
||||||
output after two-tree merge.
|
output after two-tree merge.
|
||||||
|
|
||||||
|
|
||||||
@ -150,31 +156,39 @@ output after two-tree merge.
|
|||||||
Each "index" entry has two bits worth of "stage" state. stage 0 is the
|
Each "index" entry has two bits worth of "stage" state. stage 0 is the
|
||||||
normal one, and is the only one you'd see in any kind of normal use.
|
normal one, and is the only one you'd see in any kind of normal use.
|
||||||
|
|
||||||
However, when you do "git-read-tree" with three trees, the "stage"
|
However, when you do `git-read-tree` with three trees, the "stage"
|
||||||
starts out at 1.
|
starts out at 1.
|
||||||
|
|
||||||
This means that you can do
|
This means that you can do
|
||||||
|
|
||||||
git-read-tree -m <tree1> <tree2> <tree3>
|
----------------
|
||||||
|
$ git-read-tree -m <tree1> <tree2> <tree3>
|
||||||
|
----------------
|
||||||
|
|
||||||
and you will end up with an index with all of the <tree1> entries in
|
and you will end up with an index with all of the <tree1> entries in
|
||||||
"stage1", all of the <tree2> entries in "stage2" and all of the
|
"stage1", all of the <tree2> entries in "stage2" and all of the
|
||||||
<tree3> entries in "stage3".
|
<tree3> entries in "stage3". When performing a merge of another
|
||||||
|
branch into the current branch, we use the common ancestor tree
|
||||||
|
as <tree1>, the current branch head as <tree2>, and the other
|
||||||
|
branch head as <tree3>.
|
||||||
|
|
||||||
Furthermore, "git-read-tree" has special-case logic that says: if you see
|
Furthermore, `git-read-tree` has special-case logic that says: if you see
|
||||||
a file that matches in all respects in the following states, it
|
a file that matches in all respects in the following states, it
|
||||||
"collapses" back to "stage0":
|
"collapses" back to "stage0":
|
||||||
|
|
||||||
- stage 2 and 3 are the same; take one or the other (it makes no
|
- stage 2 and 3 are the same; take one or the other (it makes no
|
||||||
difference - the same work has been done on stage 2 and 3)
|
difference - the same work has been done on our branch in
|
||||||
|
stage 2 and their branch in stage 3)
|
||||||
|
|
||||||
- stage 1 and stage 2 are the same and stage 3 is different; take
|
- stage 1 and stage 2 are the same and stage 3 is different; take
|
||||||
stage 3 (some work has been done on stage 3)
|
stage 3 (our branch in stage 2 did not do anything since the
|
||||||
|
ancestor in stage 1 while their branch in stage 3 worked on
|
||||||
|
it)
|
||||||
|
|
||||||
- stage 1 and stage 3 are the same and stage 2 is different take
|
- stage 1 and stage 3 are the same and stage 2 is different take
|
||||||
stage 2 (some work has been done on stage 2)
|
stage 2 (we did something while they did nothing)
|
||||||
|
|
||||||
The "git-write-tree" command refuses to write a nonsensical tree, and it
|
The `git-write-tree` command refuses to write a nonsensical tree, and it
|
||||||
will complain about unmerged entries if it sees a single entry that is not
|
will complain about unmerged entries if it sees a single entry that is not
|
||||||
stage 0.
|
stage 0.
|
||||||
|
|
||||||
@ -214,12 +228,10 @@ populated. Here is an outline of how the algorithm works:
|
|||||||
matching "stage1" entry if it exists too. .. all the normal
|
matching "stage1" entry if it exists too. .. all the normal
|
||||||
trivial rules ..
|
trivial rules ..
|
||||||
|
|
||||||
You would normally use "git-merge-index" with supplied
|
You would normally use `git-merge-index` with supplied
|
||||||
"git-merge-one-file" to do this last step. The script
|
`git-merge-one-file` to do this last step. The script updates
|
||||||
does not touch the files in the work tree, and the entire merge
|
the files in the working tree as it merges each path and at the
|
||||||
happens in the index file. In other words, there is no need to
|
end of a successful merge.
|
||||||
worry about what is in the working directory, since it is never
|
|
||||||
shown and never used.
|
|
||||||
|
|
||||||
When you start a 3-way merge with an index file that is already
|
When you start a 3-way merge with an index file that is already
|
||||||
populated, it is assumed that it represents the state of the
|
populated, it is assumed that it represents the state of the
|
||||||
@ -230,33 +242,54 @@ merge refuses to run if it finds an entry in the original index
|
|||||||
file that does not match stage 2.
|
file that does not match stage 2.
|
||||||
|
|
||||||
This is done to prevent you from losing your work-in-progress
|
This is done to prevent you from losing your work-in-progress
|
||||||
changes. To illustrate, suppose you start from what has been
|
changes, and mixing your random changes in an unrelated merge
|
||||||
|
commit. To illustrate, suppose you start from what has been
|
||||||
commited last to your repository:
|
commited last to your repository:
|
||||||
|
|
||||||
$ JC=`cat .git/HEAD`
|
----------------
|
||||||
$ git-checkout-index -f -u -a $JC
|
$ 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
|
You do random edits, without running git-update-index. And then
|
||||||
you notice that the tip of your "upstream" tree has advanced
|
you notice that the tip of your "upstream" tree has advanced
|
||||||
since you pulled from him:
|
since you pulled from him:
|
||||||
|
|
||||||
$ git-fetch rsync://.... linus
|
----------------
|
||||||
$ LT=`cat .git/MERGE_HEAD`
|
$ git-fetch git://.... linus
|
||||||
|
$ LT=`cat .git/FETCH_HEAD`
|
||||||
|
----------------
|
||||||
|
|
||||||
Your work tree is still based on your HEAD ($JC), but you have
|
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
|
some edits since. Three-way merge makes sure that you have not
|
||||||
added or modified index 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:
|
then does the right thing. So with the following sequence:
|
||||||
|
|
||||||
$ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT
|
----------------
|
||||||
$ git-merge-index git-merge-one-file -a
|
$ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT
|
||||||
$ echo "Merge with Linus" | \
|
$ git-merge-index git-merge-one-file -a
|
||||||
git-commit-tree `git-write-tree` -p $JC -p $LT
|
$ echo "Merge with Linus" | \
|
||||||
|
git-commit-tree `git-write-tree` -p $JC -p $LT
|
||||||
|
----------------
|
||||||
|
|
||||||
what you would commit is a pure merge between $JC and LT without
|
what you would commit is a pure merge between $JC and $LT without
|
||||||
your work-in-progress changes, and your work tree would be
|
your work-in-progress changes, and your work tree would be
|
||||||
updated to the result of the merge.
|
updated to the result of the merge.
|
||||||
|
|
||||||
|
However, if you have local changes in the working tree that
|
||||||
|
would be overwritten by this merge,`git-read-tree` will refuse
|
||||||
|
to run to prevent your changes from being lost.
|
||||||
|
|
||||||
|
In other words, there is no need to worry about what exists only
|
||||||
|
in the working tree. When you have local changes in a part of
|
||||||
|
the project that is not involved in the merge, your changes do
|
||||||
|
not interfere with the merge, and are kept intact. When they
|
||||||
|
*do* interfere, the merge does not even start (`git-read-tree`
|
||||||
|
complains loudly and fails without modifying anything). In such
|
||||||
|
a case, you can simply continue doing what you were in the
|
||||||
|
middle of doing, and when your working tree is ready (i.e. you
|
||||||
|
have finished your work-in-progress), attempt the merge again.
|
||||||
|
|
||||||
|
|
||||||
See Also
|
See Also
|
||||||
--------
|
--------
|
||||||
|
@ -71,6 +71,10 @@ packed and is served via a dumb transport.
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
exec git-update-server-info
|
exec git-update-server-info
|
||||||
|
|
||||||
|
There are other real-world examples of using update and
|
||||||
|
post-update hooks found in the Documentation/howto directory.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
<directory>::
|
<directory>::
|
||||||
|
@ -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
|
|
||||||
|
|
@ -9,7 +9,7 @@ objects into pack files.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-repack' [-a] [-d]
|
'git-repack' [-a] [-d] [-l] [-n]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -39,6 +39,13 @@ OPTIONS
|
|||||||
After packing, if the newly created packs make some
|
After packing, if the newly created packs make some
|
||||||
existing packs redundant, remove the redundant packs.
|
existing packs redundant, remove the redundant packs.
|
||||||
|
|
||||||
|
-l::
|
||||||
|
Pass the `--local` option to `git pack-objects`, see
|
||||||
|
gitlink:git-pack-objects[1].
|
||||||
|
|
||||||
|
-n::
|
||||||
|
Do not update the server information with
|
||||||
|
`git update-server-info`.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
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,23 +14,137 @@ DESCRIPTION
|
|||||||
Sets the current head to the specified commit and optionally resets the
|
Sets the current head to the specified commit and optionally resets the
|
||||||
index and working tree to match.
|
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
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
--mixed::
|
--mixed::
|
||||||
Like --soft but reports what has not been updated. This is the
|
Resets the index but not the working tree (ie, the changed files
|
||||||
default action.
|
are preserved but not marked for commit) and reports what has not
|
||||||
|
been updated. This is the default action.
|
||||||
|
|
||||||
--soft::
|
--soft::
|
||||||
Does not touch the index file nor the working tree at all, but
|
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::
|
--hard::
|
||||||
Matches the working tree and index to that of the tree being
|
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-ish>::
|
||||||
Commit to make the current HEAD.
|
Commit to make the current HEAD.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
Undo a commit and redo::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git commit ...
|
||||||
|
$ git reset --soft HEAD^ <1>
|
||||||
|
$ edit <2>
|
||||||
|
$ git commit -a -c ORIG_HEAD <3>
|
||||||
|
|
||||||
|
<1> This is most often done when you remembered what you
|
||||||
|
just committed is incomplete, or you misspelled your commit
|
||||||
|
message, or both. Leaves working tree as it was before "reset".
|
||||||
|
<2> make corrections to working tree files.
|
||||||
|
<3> "reset" copies the old head to .git/ORIG_HEAD; redo the
|
||||||
|
commit by starting with its log message. If you do not need to
|
||||||
|
edit the message further, you can give -C option instead.
|
||||||
|
------------
|
||||||
|
|
||||||
|
Undo commits permanently::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git commit ...
|
||||||
|
$ git reset --hard HEAD~3 <1>
|
||||||
|
|
||||||
|
<1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad
|
||||||
|
and you do not want to ever see them again. Do *not* do this if
|
||||||
|
you have already given these commits to somebody else.
|
||||||
|
------------
|
||||||
|
|
||||||
|
Undo a commit, making it a topic branch::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git branch topic/wip <1>
|
||||||
|
$ git reset --hard HEAD~3 <2>
|
||||||
|
$ git checkout topic/wip <3>
|
||||||
|
|
||||||
|
<1> You have made some commits, but realize they were premature
|
||||||
|
to be in the "master" branch. You want to continue polishing
|
||||||
|
them in a topic branch, so create "topic/wip" branch off of the
|
||||||
|
current HEAD.
|
||||||
|
<2> Rewind the master branch to get rid of those three commits.
|
||||||
|
<3> Switch to "topic/wip" branch and keep working.
|
||||||
|
------------
|
||||||
|
|
||||||
|
Undo update-index::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ edit <1>
|
||||||
|
$ git-update-index frotz.c filfre.c
|
||||||
|
$ mailx <2>
|
||||||
|
$ git reset <3>
|
||||||
|
$ git pull git://info.example.com/ nitfol <4>
|
||||||
|
|
||||||
|
<1> you are happily working on something, and find the changes
|
||||||
|
in these files are in good order. You do not want to see them
|
||||||
|
when you run "git diff", because you plan to work on other files
|
||||||
|
and changes with these files are distracting.
|
||||||
|
<2> somebody asks you to pull, and the changes sounds worthy of merging.
|
||||||
|
<3> however, you already dirtied the index (i.e. your index does
|
||||||
|
not match the HEAD commit). But you know the pull you are going
|
||||||
|
to make does not affect frotz.c nor filfre.c, so you revert the
|
||||||
|
index changes for these two files. Your changes in working tree
|
||||||
|
remain there.
|
||||||
|
<4> then you can pull and merge, leaving frotz.c and filfre.c
|
||||||
|
changes still in the working tree.
|
||||||
|
------------
|
||||||
|
|
||||||
|
Undo a merge or pull::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git pull <1>
|
||||||
|
Trying really trivial in-index merge...
|
||||||
|
fatal: Merge requires file-level merging
|
||||||
|
Nope.
|
||||||
|
...
|
||||||
|
Auto-merging nitfol
|
||||||
|
CONFLICT (content): Merge conflict in nitfol
|
||||||
|
Automatic merge failed/prevented; fix up by hand
|
||||||
|
$ git reset --hard <2>
|
||||||
|
|
||||||
|
<1> try to update from the upstream resulted in a lot of
|
||||||
|
conflicts; you were not ready to spend a lot of time merging
|
||||||
|
right now, so you decide to do that later.
|
||||||
|
<2> "pull" has not made merge commit, so "git reset --hard"
|
||||||
|
which is a synonym for "git reset --hard HEAD" clears the mess
|
||||||
|
from the index file and the working tree.
|
||||||
|
|
||||||
|
$ git pull . topic/branch <3>
|
||||||
|
Updating from 41223... to 13134...
|
||||||
|
Fast forward
|
||||||
|
$ git reset --hard ORIG_HEAD <4>
|
||||||
|
|
||||||
|
<3> merge a topic branch into the current branch, which resulted
|
||||||
|
in a fast forward.
|
||||||
|
<4> but you decided that the topic branch is not ready for public
|
||||||
|
consumption yet. "pull" or "merge" always leaves the original
|
||||||
|
tip of the current branch in ORIG_HEAD, so resetting hard to it
|
||||||
|
brings your index file and the working tree back to that state,
|
||||||
|
and resets the tip of the branch to that commit.
|
||||||
|
------------
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Junio C Hamano <junkio@cox.net> and Linus Torvalds <torvalds@osdl.org>
|
Written by Junio C Hamano <junkio@cox.net> and Linus Torvalds <torvalds@osdl.org>
|
||||||
|
@ -7,7 +7,7 @@ git-revert - Revert an existing commit.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-revert' [-n] <commit>
|
'git-revert' [--edit | --no-edit] [-n] <commit>
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -20,7 +20,16 @@ OPTIONS
|
|||||||
<commit>::
|
<commit>::
|
||||||
Commit to revert.
|
Commit to revert.
|
||||||
|
|
||||||
-n::
|
-e|--edit::
|
||||||
|
With this option, `git-revert` will let you edit the commit
|
||||||
|
message prior committing the revert. This is the default if
|
||||||
|
you run the command from a terminal.
|
||||||
|
|
||||||
|
--no-edit::
|
||||||
|
With this option, `git-revert` will not start the commit
|
||||||
|
message editor.
|
||||||
|
|
||||||
|
-n|--no-commit::
|
||||||
Usually the command automatically creates a commit with
|
Usually the command automatically creates a commit with
|
||||||
a commit log message stating which commit was reverted.
|
a commit log message stating which commit was reverted.
|
||||||
This flag applies the change necessary to revert the
|
This flag applies the change necessary to revert the
|
||||||
|
@ -7,23 +7,40 @@ git-show-branch - Show branches and their commits.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-show-branch [--all] [--heads] [--tags] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] <reference>...'
|
'git-show-branch [--all] [--heads] [--tags] [--topo-order] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [<rev> | <glob>]...'
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Shows the head commits from the named <reference> (or all refs under
|
|
||||||
$GIT_DIR/refs/heads), and displays concise list of commit logs
|
Shows the commit ancestry graph starting from the commits named
|
||||||
to show their relationship semi-visually.
|
with <rev>s or <globs>s (or all refs under $GIT_DIR/refs/heads
|
||||||
|
and/or $GIT_DIR/refs/tags) semi-visually.
|
||||||
|
|
||||||
|
It cannot show more than 29 branches and commits at a time.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
<reference>::
|
<rev>::
|
||||||
Name of the reference under $GIT_DIR/refs/.
|
Arbitrary extended SHA1 expression (see `git-rev-parse`)
|
||||||
|
that typically names a branch HEAD or a tag.
|
||||||
|
|
||||||
|
<glob>::
|
||||||
|
A glob pattern that matches branch or tag names under
|
||||||
|
$GIT_DIR/refs. For example, if you have many topic
|
||||||
|
branches under $GIT_DIR/refs/heads/topic, giving
|
||||||
|
`topic/*` would show all of them.
|
||||||
|
|
||||||
--all --heads --tags::
|
--all --heads --tags::
|
||||||
Show all refs under $GIT_DIR/refs, $GIT_DIR/refs/heads,
|
Show all refs under $GIT_DIR/refs, $GIT_DIR/refs/heads,
|
||||||
and $GIT_DIR/refs/tags, respectively.
|
and $GIT_DIR/refs/tags, respectively.
|
||||||
|
|
||||||
|
--topo-order::
|
||||||
|
By default, the branches and their commits are shown in
|
||||||
|
reverse chronological order. This option makes them
|
||||||
|
appear in topological order (i.e., descendant commits
|
||||||
|
are shown before their parents).
|
||||||
|
|
||||||
--more=<n>::
|
--more=<n>::
|
||||||
Usually the command stops output upon showing the commit
|
Usually the command stops output upon showing the commit
|
||||||
that is the common ancestor of all the branches. This
|
that is the common ancestor of all the branches. This
|
||||||
|
@ -10,7 +10,7 @@ git-svnimport - Import a SVN repository into git
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-svnimport' [ -o <branch-for-HEAD> ] [ -h ] [ -v ] [ -d | -D ]
|
'git-svnimport' [ -o <branch-for-HEAD> ] [ -h ] [ -v ] [ -d | -D ]
|
||||||
[ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_nr_changes]
|
[ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_rev]
|
||||||
[ -b branch_subdir ] [ -t trunk_subdir ] [ -T tag_subdir ]
|
[ -b branch_subdir ] [ -t trunk_subdir ] [ -T tag_subdir ]
|
||||||
[ -s start_chg ] [ -m ] [ -M regex ]
|
[ -s start_chg ] [ -m ] [ -M regex ]
|
||||||
<SVN_repository_URL> [ <path> ]
|
<SVN_repository_URL> [ <path> ]
|
||||||
@ -71,14 +71,11 @@ When importing incementally, you might need to edit the .git/svn2git file.
|
|||||||
regex. It can be used with -m to also see the default regexes.
|
regex. It can be used with -m to also see the default regexes.
|
||||||
You must escape forward slashes.
|
You must escape forward slashes.
|
||||||
|
|
||||||
-l <max_num_changes>::
|
-l <max_rev>::
|
||||||
Limit the number of SVN changesets we pull before quitting.
|
Specify a maximum revision number to pull.
|
||||||
This option is necessary because the SVN library has serious memory
|
|
||||||
leaks; the recommended value for nontrivial imports is 100.
|
|
||||||
|
|
||||||
git-svnimport will still exit with a zero exit code. You can check
|
Formerly, this option controlled how many revisions to pull, due to
|
||||||
the size of the file ".git/svn2git" to determine whether to call
|
SVN memory leaks. (These have been worked around.)
|
||||||
the importer again.
|
|
||||||
|
|
||||||
-v::
|
-v::
|
||||||
Verbosity: let 'svnimport' report what it is doing.
|
Verbosity: let 'svnimport' report what it is doing.
|
||||||
|
@ -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
|
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`.
|
to find out which branch we are on, we did `readlink .git/HEAD`.
|
||||||
This was fine, and internally that is what still happens by
|
This was fine, and internally that is what still happens by
|
||||||
default, but on platforms that does not have working symlinks,
|
default, but on platforms that do not have working symlinks,
|
||||||
or that does not have the `readlink(1)` command, this was a bit
|
or that do not have the `readlink(1)` command, this was a bit
|
||||||
cumbersome. On some platforms, `ln -sf` does not even work as
|
cumbersome. On some platforms, `ln -sf` does not even work as
|
||||||
advertised (horrors).
|
advertised (horrors).
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ creates a 'tag' object, and requires the tag message. Unless
|
|||||||
in the tag message.
|
in the tag message.
|
||||||
|
|
||||||
Otherwise just the SHA1 object name of the commit object is
|
Otherwise just the SHA1 object name of the commit object is
|
||||||
written (i.e. an lightweight tag).
|
written (i.e. a lightweight tag).
|
||||||
|
|
||||||
A GnuPG signed tag object will be created when `-s` or `-u
|
A GnuPG signed tag object will be created when `-s` or `-u
|
||||||
<key-id>` is used. When `-u <key-id>` is not used, the
|
<key-id>` is used. When `-u <key-id>` is not used, the
|
||||||
@ -32,6 +32,26 @@ GnuPG key for signing.
|
|||||||
|
|
||||||
`-d <tag>` deletes the tag.
|
`-d <tag>` deletes the tag.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
-a::
|
||||||
|
Make an unsigned, annotated tag object
|
||||||
|
|
||||||
|
-s::
|
||||||
|
Make a GPG-signed tag, using the default e-mail address's key
|
||||||
|
|
||||||
|
-u <key-id>::
|
||||||
|
Make a GPG-signed tag, using the given key
|
||||||
|
|
||||||
|
-f::
|
||||||
|
Replace an existing tag with the given name (instead of failing)
|
||||||
|
|
||||||
|
-d::
|
||||||
|
Delete an existing tag with the given name
|
||||||
|
|
||||||
|
-m <msg>::
|
||||||
|
Use the given tag message (instead of prompting)
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -8,7 +8,7 @@ git-unpack-objects - Unpack objects from a packed archive.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-unpack-objects' [-q] <pack-file
|
'git-unpack-objects' [-n] [-q] <pack-file
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -19,6 +19,10 @@ one-object" format in $GIT_OBJECT_DIRECTORY.
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
-n::
|
||||||
|
Only list the objects that would be unpacked, don't actually unpack
|
||||||
|
them.
|
||||||
|
|
||||||
-q::
|
-q::
|
||||||
The command usually shows percentage progress. This
|
The command usually shows percentage progress. This
|
||||||
flag suppresses it.
|
flag suppresses it.
|
||||||
|
@ -60,7 +60,7 @@ OPTIONS
|
|||||||
Directly insert the specified info into the index.
|
Directly insert the specified info into the index.
|
||||||
|
|
||||||
--index-info::
|
--index-info::
|
||||||
Read index info from stdin.
|
Read index information from stdin.
|
||||||
|
|
||||||
--chmod=(+|-)x::
|
--chmod=(+|-)x::
|
||||||
Set the execute permissions on the updated files.
|
Set the execute permissions on the updated files.
|
||||||
@ -123,7 +123,9 @@ merging.
|
|||||||
|
|
||||||
To pretend you have a file with mode and sha1 at path, say:
|
To pretend you have a file with mode and sha1 at path, say:
|
||||||
|
|
||||||
$ git-update-index --cacheinfo mode sha1 path
|
----------------
|
||||||
|
$ git-update-index --cacheinfo mode sha1 path
|
||||||
|
----------------
|
||||||
|
|
||||||
'--info-only' is used to register files without placing them in the object
|
'--info-only' is used to register files without placing them in the object
|
||||||
database. This is useful for status-only repositories.
|
database. This is useful for status-only repositories.
|
||||||
@ -134,11 +136,70 @@ in the database but the file isn't available locally. '--info-only' is
|
|||||||
useful when the file is available, but you do not wish to update the
|
useful when the file is available, but you do not wish to update the
|
||||||
object database.
|
object database.
|
||||||
|
|
||||||
|
|
||||||
|
Using --index-info
|
||||||
|
------------------
|
||||||
|
|
||||||
|
`--index-info` is a more powerful mechanism that lets you feed
|
||||||
|
multiple entry definitions from the standard input, and designed
|
||||||
|
specifically for scripts. It can take inputs of three formats:
|
||||||
|
|
||||||
|
. mode SP sha1 TAB path
|
||||||
|
+
|
||||||
|
The first format is what "git-apply --index-info"
|
||||||
|
reports, and used to reconstruct a partial tree
|
||||||
|
that is used for phony merge base tree when falling
|
||||||
|
back on 3-way merge.
|
||||||
|
|
||||||
|
. mode SP type SP sha1 TAB path
|
||||||
|
+
|
||||||
|
The second format is to stuff git-ls-tree output
|
||||||
|
into the index file.
|
||||||
|
|
||||||
|
. mode SP sha1 SP stage TAB path
|
||||||
|
+
|
||||||
|
This format is to put higher order stages into the
|
||||||
|
index file and matches git-ls-files --stage output.
|
||||||
|
|
||||||
|
To place a higher stage entry to the index, the path should
|
||||||
|
first be removed by feeding a mode=0 entry for the path, and
|
||||||
|
then feeding necessary input lines in the third format.
|
||||||
|
|
||||||
|
For example, starting with this index:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git ls-files -s
|
||||||
|
100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz
|
||||||
|
------------
|
||||||
|
|
||||||
|
you can feed the following input to `--index-info`:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git update-index --index-info
|
||||||
|
0 0000000000000000000000000000000000000000 frotz
|
||||||
|
100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz
|
||||||
|
100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz
|
||||||
|
------------
|
||||||
|
|
||||||
|
The first line of the input feeds 0 as the mode to remove the
|
||||||
|
path; the SHA1 does not matter as long as it is well formatted.
|
||||||
|
Then the second and third line feeds stage 1 and stage 2 entries
|
||||||
|
for that path. After the above, we would end up with this:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git ls-files -s
|
||||||
|
100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz
|
||||||
|
100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
To update and refresh only the files already checked out:
|
To update and refresh only the files already checked out:
|
||||||
|
|
||||||
git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
|
----------------
|
||||||
|
$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
|
||||||
|
----------------
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
@ -146,12 +207,18 @@ Configuration
|
|||||||
|
|
||||||
The command honors `core.filemode` configuration variable. If
|
The command honors `core.filemode` configuration variable. If
|
||||||
your repository is on an filesystem whose executable bits are
|
your repository is on an filesystem whose executable bits are
|
||||||
unreliable, this should be set to 'false'. This causes the
|
unreliable, this should be set to 'false' (see gitlink:git-repo-config[1]).
|
||||||
command to ignore differences in file modes recorded in the
|
This causes the command to ignore differences in file modes recorded
|
||||||
index and the file mode on the filesystem if they differ only on
|
in the index and the file mode on the filesystem if they differ only on
|
||||||
executable bit. On such an unfortunate filesystem, you may
|
executable bit. On such an unfortunate filesystem, you may
|
||||||
need to use `git-update-index --chmod=`.
|
need to use `git-update-index --chmod=`.
|
||||||
|
|
||||||
|
|
||||||
|
See Also
|
||||||
|
--------
|
||||||
|
gitlink:git-repo-config[1]
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org>
|
Written by Linus Torvalds <torvalds@osdl.org>
|
||||||
|
@ -12,17 +12,17 @@ SYNOPSIS
|
|||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
A dumb server that does not do on-the-fly pack generations can
|
A dumb server that does not do on-the-fly pack generations must
|
||||||
have some auxiliary information files in $GIT_DIR/info and
|
have some auxiliary information files in $GIT_DIR/info and
|
||||||
$GIT_OBJECT_DIRECTORY/info directories to help clients discover
|
$GIT_OBJECT_DIRECTORY/info directories to help clients discover
|
||||||
what references and packs the server has and make optimized
|
what references and packs the server has. This command
|
||||||
pull decisions. This command generates such auxiliary files.
|
generates such auxiliary files.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
|
||||||
--force::
|
-f|--force::
|
||||||
Update the info files from scratch.
|
Update the info files from scratch.
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ git-verify-pack - Validate packed git archive files.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-verify-pack' [-v] <pack>.idx ...
|
'git-verify-pack' [-v] [--] <pack>.idx ...
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -25,6 +25,8 @@ OPTIONS
|
|||||||
-v::
|
-v::
|
||||||
After verifying the pack, show list of objects contained
|
After verifying the pack, show list of objects contained
|
||||||
in the pack.
|
in the pack.
|
||||||
|
--::
|
||||||
|
Do not interpret any more arguments as options.
|
||||||
|
|
||||||
OUTPUT FORMAT
|
OUTPUT FORMAT
|
||||||
-------------
|
-------------
|
||||||
|
@ -14,19 +14,21 @@ DESCRIPTION
|
|||||||
-----------
|
-----------
|
||||||
Creates a tree object using the current index.
|
Creates a tree object using the current index.
|
||||||
|
|
||||||
The index must be merged.
|
The index must be in a fully merged state.
|
||||||
|
|
||||||
Conceptually, "git-write-tree" sync()s the current index contents
|
Conceptually, `git-write-tree` sync()s the current index contents
|
||||||
into a set of tree files.
|
into a set of tree files.
|
||||||
In order to have that match what is actually in your directory right
|
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
|
now, you need to have done a `git-update-index` phase before you did the
|
||||||
"git-write-tree".
|
`git-write-tree`.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
--missing-ok::
|
--missing-ok::
|
||||||
Normally "git-write-tree" ensures that the objects referenced by the
|
Normally `git-write-tree` ensures that the objects referenced by the
|
||||||
directory exist in the object database. This option disables this check.
|
directory exist in the object database. This option disables this
|
||||||
|
check.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -8,39 +8,70 @@ git - the stupid content tracker
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-<command>' <args>
|
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ARGS]
|
||||||
|
|
||||||
DESCRIPTION
|
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.
|
||||||
|
|
||||||
Before reading this cover to cover, you may want to take a look
|
--help::
|
||||||
at the link:tutorial.html[tutorial] document.
|
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.
|
||||||
|
|
||||||
The <<Discussion>> section below contains much useful definition and
|
--exec-path::
|
||||||
clarification info - read that first. And of the commands, I suggest
|
path to wherever your core git programs are installed.
|
||||||
reading gitlink:git-update-index[1] and
|
This can also be controlled by setting the GIT_EXEC_PATH
|
||||||
gitlink:git-read-tree[1] first - I wish I had!
|
environment variable. If no path is given 'git' will print
|
||||||
|
the current setting and then exit.
|
||||||
|
|
||||||
If you are migrating from CVS, link:cvs-migration.html[cvs migration]
|
|
||||||
document may be helpful after you finish the tutorial.
|
NOT LEARNING CORE GIT COMMANDS
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
This manual is intended to give complete background information
|
||||||
|
and internal workings of git, which may be too much for most
|
||||||
|
people. The <<Discussion>> section below contains much useful
|
||||||
|
definition and clarification - read that first.
|
||||||
|
|
||||||
|
If you are interested in using git to manage (version control)
|
||||||
|
projects, use link:everyday.html[Everyday GIT] as a guide to the
|
||||||
|
minimum set of commands you need to know for day-to-day work.
|
||||||
|
Most likely, that will get you started, and you can go a long
|
||||||
|
way without knowing the low level details too much.
|
||||||
|
|
||||||
|
The link:tutorial.html[tutorial] document covers how things
|
||||||
|
internally work.
|
||||||
|
|
||||||
|
If you are migrating from CVS, link:cvs-migration.html[cvs
|
||||||
|
migration] document may be helpful after you finish the
|
||||||
|
tutorial.
|
||||||
|
|
||||||
After you get the general feel from the tutorial and this
|
After you get the general feel from the tutorial and this
|
||||||
overview page, you may want to take a look at the
|
overview page, you may want to take a look at the
|
||||||
link:howto-index.html[howto] documents.
|
link:howto-index.html[howto] documents.
|
||||||
|
|
||||||
|
|
||||||
David Greaves <david@dgreaves.com>
|
CORE GIT COMMANDS
|
||||||
08/05/05
|
-----------------
|
||||||
|
|
||||||
|
If you are writing your own Porcelain, you need to be familiar
|
||||||
|
with most of the low level commands --- I suggest starting from
|
||||||
|
gitlink:git-update-index[1] and gitlink:git-read-tree[1].
|
||||||
|
|
||||||
Updated by Junio C Hamano <junkio@cox.net> on 2005-05-05 to
|
|
||||||
reflect recent changes.
|
|
||||||
|
|
||||||
Commands Overview
|
Commands Overview
|
||||||
-----------------
|
-----------------
|
||||||
The git commands can helpfully be split into those that manipulate
|
The git commands can helpfully be split into those that manipulate
|
||||||
the repository, the index and the working fileset, those that
|
the repository, the index and the files in the working tree, those that
|
||||||
interrogate and compare them, and those that moves objects and
|
interrogate and compare them, and those that moves objects and
|
||||||
references between repositories.
|
references between repositories.
|
||||||
|
|
||||||
@ -59,25 +90,26 @@ gitlink:git-apply[1]::
|
|||||||
applies it to the working tree.
|
applies it to the working tree.
|
||||||
|
|
||||||
gitlink:git-checkout-index[1]::
|
gitlink:git-checkout-index[1]::
|
||||||
Copy files from the index to the working directory
|
Copy files from the index to the working tree.
|
||||||
|
|
||||||
gitlink:git-commit-tree[1]::
|
gitlink:git-commit-tree[1]::
|
||||||
Creates a new commit object
|
Creates a new commit object.
|
||||||
|
|
||||||
gitlink:git-hash-object[1]::
|
gitlink:git-hash-object[1]::
|
||||||
Computes the object ID from a file.
|
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.
|
Build pack idx file for an existing packed archive.
|
||||||
|
|
||||||
gitlink:git-init-db[1]::
|
gitlink:git-init-db[1]::
|
||||||
Creates an empty git object database
|
Creates an empty git object database, or reinitialize an
|
||||||
|
existing one.
|
||||||
|
|
||||||
gitlink:git-merge-index[1]::
|
gitlink:git-merge-index[1]::
|
||||||
Runs a merge for files needing merging
|
Runs a merge for files needing merging.
|
||||||
|
|
||||||
gitlink:git-mktag[1]::
|
gitlink:git-mktag[1]::
|
||||||
Creates a tag object
|
Creates a tag object.
|
||||||
|
|
||||||
gitlink:git-pack-objects[1]::
|
gitlink:git-pack-objects[1]::
|
||||||
Creates a packed archive of objects.
|
Creates a packed archive of objects.
|
||||||
@ -86,71 +118,77 @@ gitlink:git-prune-packed[1]::
|
|||||||
Remove extra objects that are already in pack files.
|
Remove extra objects that are already in pack files.
|
||||||
|
|
||||||
gitlink:git-read-tree[1]::
|
gitlink:git-read-tree[1]::
|
||||||
Reads tree information into the directory index
|
Reads tree information into the index.
|
||||||
|
|
||||||
|
gitlink:git-repo-config[1]::
|
||||||
|
Get and set options in .git/config.
|
||||||
|
|
||||||
gitlink:git-unpack-objects[1]::
|
gitlink:git-unpack-objects[1]::
|
||||||
Unpacks objects out of a packed archive.
|
Unpacks objects out of a packed archive.
|
||||||
|
|
||||||
gitlink:git-update-index[1]::
|
gitlink:git-update-index[1]::
|
||||||
Modifies the index or directory cache
|
Registers files in the working tree to the index.
|
||||||
|
|
||||||
gitlink:git-write-tree[1]::
|
gitlink:git-write-tree[1]::
|
||||||
Creates a tree from the current index
|
Creates a tree from the index.
|
||||||
|
|
||||||
|
|
||||||
Interrogation commands
|
Interrogation commands
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
gitlink:git-cat-file[1]::
|
gitlink:git-cat-file[1]::
|
||||||
Provide content or type information for repository objects
|
Provide content or type/size information for repository objects.
|
||||||
|
|
||||||
gitlink:git-diff-index[1]::
|
gitlink:git-diff-index[1]::
|
||||||
Compares content and mode of blobs between the index and repository
|
Compares content and mode of blobs between the index and repository.
|
||||||
|
|
||||||
gitlink:git-diff-files[1]::
|
gitlink:git-diff-files[1]::
|
||||||
Compares files in the working tree and the index
|
Compares files in the working tree and the index.
|
||||||
|
|
||||||
gitlink:git-diff-stages[1]::
|
gitlink:git-diff-stages[1]::
|
||||||
Compares two "merge stages" in the index file.
|
Compares two "merge stages" in the index.
|
||||||
|
|
||||||
gitlink:git-diff-tree[1]::
|
gitlink:git-diff-tree[1]::
|
||||||
Compares the content and mode of blobs found via two tree objects
|
Compares the content and mode of blobs found via two tree objects.
|
||||||
|
|
||||||
gitlink:git-fsck-objects[1]::
|
gitlink:git-fsck-objects[1]::
|
||||||
Verifies the connectivity and validity of the objects in the database
|
Verifies the connectivity and validity of the objects in the database.
|
||||||
|
|
||||||
gitlink:git-ls-files[1]::
|
gitlink:git-ls-files[1]::
|
||||||
Information about files in the index/working directory
|
Information about files in the index and the working tree.
|
||||||
|
|
||||||
gitlink:git-ls-tree[1]::
|
gitlink:git-ls-tree[1]::
|
||||||
Displays a tree object in human readable form
|
Displays a tree object in human readable form.
|
||||||
|
|
||||||
gitlink:git-merge-base[1]::
|
gitlink:git-merge-base[1]::
|
||||||
Finds as good a common ancestor as possible for a merge
|
Finds as good common ancestors as possible for a merge.
|
||||||
|
|
||||||
gitlink:git-name-rev[1]::
|
gitlink:git-name-rev[1]::
|
||||||
Find symbolic names for given revs
|
Find symbolic names for given revs.
|
||||||
|
|
||||||
|
gitlink:git-pack-redundant[1]::
|
||||||
|
Find redundant pack files.
|
||||||
|
|
||||||
gitlink:git-rev-list[1]::
|
gitlink:git-rev-list[1]::
|
||||||
Lists commit objects in reverse chronological order
|
Lists commit objects in reverse chronological order.
|
||||||
|
|
||||||
gitlink:git-show-index[1]::
|
gitlink:git-show-index[1]::
|
||||||
Displays contents of a pack idx file.
|
Displays contents of a pack idx file.
|
||||||
|
|
||||||
gitlink:git-tar-tree[1]::
|
gitlink:git-tar-tree[1]::
|
||||||
Creates a tar archive of the files in the named tree
|
Creates a tar archive of the files in the named tree object.
|
||||||
|
|
||||||
gitlink:git-unpack-file[1]::
|
gitlink:git-unpack-file[1]::
|
||||||
Creates a temporary file with a blob's contents
|
Creates a temporary file with a blob's contents.
|
||||||
|
|
||||||
gitlink:git-var[1]::
|
gitlink:git-var[1]::
|
||||||
Displays a git logical variable
|
Displays a git logical variable.
|
||||||
|
|
||||||
gitlink:git-verify-pack[1]::
|
gitlink:git-verify-pack[1]::
|
||||||
Validates packed git archive files
|
Validates packed git archive files.
|
||||||
|
|
||||||
The interrogate commands may create files - and you can force them to
|
In general, the interrogate commands do not touch the files in
|
||||||
touch the working file set - but in general they don't
|
the working tree.
|
||||||
|
|
||||||
|
|
||||||
Synching repositories
|
Synching repositories
|
||||||
@ -158,19 +196,24 @@ Synching repositories
|
|||||||
|
|
||||||
gitlink:git-clone-pack[1]::
|
gitlink:git-clone-pack[1]::
|
||||||
Clones a repository into the current repository (engine
|
Clones a repository into the current repository (engine
|
||||||
for ssh and local transport)
|
for ssh and local transport).
|
||||||
|
|
||||||
gitlink:git-fetch-pack[1]::
|
gitlink:git-fetch-pack[1]::
|
||||||
Updates from a remote repository.
|
Updates from a remote repository (engine for ssh and
|
||||||
|
local transport).
|
||||||
|
|
||||||
gitlink:git-http-fetch[1]::
|
gitlink:git-http-fetch[1]::
|
||||||
Downloads a remote git repository via HTTP
|
Downloads a remote git repository via HTTP by walking
|
||||||
|
commit chain.
|
||||||
|
|
||||||
gitlink:git-local-fetch[1]::
|
gitlink:git-local-fetch[1]::
|
||||||
Duplicates another git repository on a local system
|
Duplicates another git repository on a local system by
|
||||||
|
walking commit chain.
|
||||||
|
|
||||||
gitlink:git-peek-remote[1]::
|
gitlink:git-peek-remote[1]::
|
||||||
Lists references on a remote repository using upload-pack protocol.
|
Lists references on a remote repository using
|
||||||
|
upload-pack protocol (engine for ssh and local
|
||||||
|
transport).
|
||||||
|
|
||||||
gitlink:git-receive-pack[1]::
|
gitlink:git-receive-pack[1]::
|
||||||
Invoked by 'git-send-pack' to receive what is pushed to it.
|
Invoked by 'git-send-pack' to receive what is pushed to it.
|
||||||
@ -178,14 +221,18 @@ gitlink:git-receive-pack[1]::
|
|||||||
gitlink:git-send-pack[1]::
|
gitlink:git-send-pack[1]::
|
||||||
Pushes to a remote repository, intelligently.
|
Pushes to a remote repository, intelligently.
|
||||||
|
|
||||||
|
gitlink:git-http-push[1]::
|
||||||
|
Push missing objects using HTTP/DAV.
|
||||||
|
|
||||||
gitlink:git-shell[1]::
|
gitlink:git-shell[1]::
|
||||||
Restricted shell for GIT-only SSH access.
|
Restricted shell for GIT-only SSH access.
|
||||||
|
|
||||||
gitlink:git-ssh-fetch[1]::
|
gitlink:git-ssh-fetch[1]::
|
||||||
Pulls from a remote repository over ssh connection
|
Pulls from a remote repository over ssh connection by
|
||||||
|
walking commit chain.
|
||||||
|
|
||||||
gitlink:git-ssh-upload[1]::
|
gitlink:git-ssh-upload[1]::
|
||||||
Helper "server-side" program used by git-ssh-fetch
|
Helper "server-side" program used by git-ssh-fetch.
|
||||||
|
|
||||||
gitlink:git-update-server-info[1]::
|
gitlink:git-update-server-info[1]::
|
||||||
Updates auxiliary information on a dumb server to help
|
Updates auxiliary information on a dumb server to help
|
||||||
@ -200,16 +247,16 @@ Porcelain-ish Commands
|
|||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
gitlink:git-add[1]::
|
gitlink:git-add[1]::
|
||||||
Add paths to the index file.
|
Add paths to the index.
|
||||||
|
|
||||||
gitlink:git-am[1]::
|
gitlink:git-am[1]::
|
||||||
Apply patches from a mailbox, but cooler.
|
Apply patches from a mailbox, but cooler.
|
||||||
|
|
||||||
gitlink:git-applymbox[1]::
|
gitlink:git-applymbox[1]::
|
||||||
Apply patches from a mailbox.
|
Apply patches from a mailbox, original version by Linus.
|
||||||
|
|
||||||
gitlink:git-bisect[1]::
|
gitlink:git-bisect[1]::
|
||||||
Find the change that introduced a bug.
|
Find the change that introduced a bug by binary search.
|
||||||
|
|
||||||
gitlink:git-branch[1]::
|
gitlink:git-branch[1]::
|
||||||
Create and Show branches.
|
Create and Show branches.
|
||||||
@ -236,7 +283,7 @@ gitlink:git-format-patch[1]::
|
|||||||
Prepare patches for e-mail submission.
|
Prepare patches for e-mail submission.
|
||||||
|
|
||||||
gitlink:git-grep[1]::
|
gitlink:git-grep[1]::
|
||||||
Print lines matching a pattern
|
Print lines matching a pattern.
|
||||||
|
|
||||||
gitlink:git-log[1]::
|
gitlink:git-log[1]::
|
||||||
Shows commit logs.
|
Shows commit logs.
|
||||||
@ -250,9 +297,6 @@ gitlink:git-merge[1]::
|
|||||||
gitlink:git-mv[1]::
|
gitlink:git-mv[1]::
|
||||||
Move or rename a file, a directory, or a symlink.
|
Move or rename a file, a directory, or a symlink.
|
||||||
|
|
||||||
gitlink:git-octopus[1]::
|
|
||||||
Merge more than two commits.
|
|
||||||
|
|
||||||
gitlink:git-pull[1]::
|
gitlink:git-pull[1]::
|
||||||
Fetch from and merge with a remote repository.
|
Fetch from and merge with a remote repository.
|
||||||
|
|
||||||
@ -260,10 +304,7 @@ gitlink:git-push[1]::
|
|||||||
Update remote refs along with associated objects.
|
Update remote refs along with associated objects.
|
||||||
|
|
||||||
gitlink:git-rebase[1]::
|
gitlink:git-rebase[1]::
|
||||||
Rebase local commits to new upstream head.
|
Rebase local commits to the updated upstream head.
|
||||||
|
|
||||||
gitlink:git-rename[1]::
|
|
||||||
Rename files and directories.
|
|
||||||
|
|
||||||
gitlink:git-repack[1]::
|
gitlink:git-repack[1]::
|
||||||
Pack unpacked objects in a repository.
|
Pack unpacked objects in a repository.
|
||||||
@ -304,19 +345,22 @@ gitlink:git-archimport[1]::
|
|||||||
Import an arch repository into git.
|
Import an arch repository into git.
|
||||||
|
|
||||||
gitlink:git-convert-objects[1]::
|
gitlink:git-convert-objects[1]::
|
||||||
Converts old-style git repository
|
Converts old-style git repository.
|
||||||
|
|
||||||
gitlink:git-cvsimport[1]::
|
gitlink:git-cvsimport[1]::
|
||||||
Salvage your data out of another SCM people love to hate.
|
Salvage your data out of another SCM people love to hate.
|
||||||
|
|
||||||
gitlink:git-lost+found[1]::
|
gitlink:git-cvsexportcommit[1]::
|
||||||
|
Export a single commit to a CVS checkout.
|
||||||
|
|
||||||
|
gitlink:git-lost-found[1]::
|
||||||
Recover lost refs that luckily have not yet been pruned.
|
Recover lost refs that luckily have not yet been pruned.
|
||||||
|
|
||||||
gitlink:git-merge-one-file[1]::
|
gitlink:git-merge-one-file[1]::
|
||||||
The standard helper program to use with "git-merge-index"
|
The standard helper program to use with `git-merge-index`.
|
||||||
|
|
||||||
gitlink:git-prune[1]::
|
gitlink:git-prune[1]::
|
||||||
Prunes all unreachable objects from the object database
|
Prunes all unreachable objects from the object database.
|
||||||
|
|
||||||
gitlink:git-relink[1]::
|
gitlink:git-relink[1]::
|
||||||
Hardlink common objects in local repositories.
|
Hardlink common objects in local repositories.
|
||||||
@ -328,10 +372,10 @@ gitlink:git-sh-setup[1]::
|
|||||||
Common git shell script setup code.
|
Common git shell script setup code.
|
||||||
|
|
||||||
gitlink:git-symbolic-ref[1]::
|
gitlink:git-symbolic-ref[1]::
|
||||||
Read and modify symbolic refs
|
Read and modify symbolic refs.
|
||||||
|
|
||||||
gitlink:git-tag[1]::
|
gitlink:git-tag[1]::
|
||||||
An example script to create a tag object signed with GPG
|
An example script to create a tag object signed with GPG.
|
||||||
|
|
||||||
gitlink:git-update-ref[1]::
|
gitlink:git-update-ref[1]::
|
||||||
Update the object name stored in a ref safely.
|
Update the object name stored in a ref safely.
|
||||||
@ -355,16 +399,19 @@ gitlink:git-get-tar-commit-id[1]::
|
|||||||
Extract commit ID from an archive created using git-tar-tree.
|
Extract commit ID from an archive created using git-tar-tree.
|
||||||
|
|
||||||
gitlink:git-mailinfo[1]::
|
gitlink:git-mailinfo[1]::
|
||||||
Extracts patch from a single e-mail message.
|
Extracts patch and authorship information from a single
|
||||||
|
e-mail message, optionally transliterating the commit
|
||||||
|
message into utf-8.
|
||||||
|
|
||||||
gitlink:git-mailsplit[1]::
|
gitlink:git-mailsplit[1]::
|
||||||
git-mailsplit.
|
A stupid program to split UNIX mbox format mailbox into
|
||||||
|
individual pieces of e-mail.
|
||||||
|
|
||||||
gitlink:git-patch-id[1]::
|
gitlink:git-patch-id[1]::
|
||||||
Compute unique ID for a patch.
|
Compute unique ID for a patch.
|
||||||
|
|
||||||
gitlink:git-parse-remote[1]::
|
gitlink:git-parse-remote[1]::
|
||||||
Routines to help parsing $GIT_DIR/remotes/
|
Routines to help parsing `$GIT_DIR/remotes/` files.
|
||||||
|
|
||||||
gitlink:git-request-pull[1]::
|
gitlink:git-request-pull[1]::
|
||||||
git-request-pull.
|
git-request-pull.
|
||||||
@ -386,22 +433,20 @@ Commands not yet documented
|
|||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
gitlink:gitk[1]::
|
gitlink:gitk[1]::
|
||||||
gitk.
|
The gitk repository browser.
|
||||||
|
|
||||||
|
|
||||||
Configuration Mechanism
|
Configuration Mechanism
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Starting from 0.99.9 (actually mid 0.99.8.GIT), .git/config file
|
Starting from 0.99.9 (actually mid 0.99.8.GIT), `.git/config` file
|
||||||
is used to hold per-repository configuration options. It is a
|
is used to hold per-repository configuration options. It is a
|
||||||
simple text file modelled after `.ini` format familiar to some
|
simple text file modelled after `.ini` format familiar to some
|
||||||
people. Here is an example:
|
people. Here is an example:
|
||||||
|
|
||||||
------------
|
------------
|
||||||
#
|
#
|
||||||
# This is the config file, and
|
# A '#' or ';' character indicates a comment.
|
||||||
# a '#' or ';' character indicates
|
|
||||||
# a comment
|
|
||||||
#
|
#
|
||||||
|
|
||||||
; core variables
|
; core variables
|
||||||
@ -423,30 +468,30 @@ their operation accordingly.
|
|||||||
Identifier Terminology
|
Identifier Terminology
|
||||||
----------------------
|
----------------------
|
||||||
<object>::
|
<object>::
|
||||||
Indicates the sha1 identifier for any type of object
|
Indicates the object name for any type of object.
|
||||||
|
|
||||||
<blob>::
|
<blob>::
|
||||||
Indicates a blob object sha1 identifier
|
Indicates a blob object name.
|
||||||
|
|
||||||
<tree>::
|
<tree>::
|
||||||
Indicates a tree object sha1 identifier
|
Indicates a tree object name.
|
||||||
|
|
||||||
<commit>::
|
<commit>::
|
||||||
Indicates a commit object sha1 identifier
|
Indicates a commit object name.
|
||||||
|
|
||||||
<tree-ish>::
|
<tree-ish>::
|
||||||
Indicates a tree, commit or tag object sha1 identifier. A
|
Indicates a tree, commit or tag object name. A
|
||||||
command that takes a <tree-ish> argument ultimately wants to
|
command that takes a <tree-ish> argument ultimately wants to
|
||||||
operate on a <tree> object but automatically dereferences
|
operate on a <tree> object but automatically dereferences
|
||||||
<commit> and <tag> objects that point at a <tree>.
|
<commit> and <tag> objects that point at a <tree>.
|
||||||
|
|
||||||
<type>::
|
<type>::
|
||||||
Indicates that an object type is required.
|
Indicates that an object type is required.
|
||||||
Currently one of: blob/tree/commit/tag
|
Currently one of: `blob`, `tree`, `commit`, or `tag`.
|
||||||
|
|
||||||
<file>::
|
<file>::
|
||||||
Indicates a filename - always relative to the root of
|
Indicates a filename - almost always relative to the
|
||||||
the tree structure GIT_INDEX_FILE describes.
|
root of the tree structure `GIT_INDEX_FILE` describes.
|
||||||
|
|
||||||
Symbolic Identifiers
|
Symbolic Identifiers
|
||||||
--------------------
|
--------------------
|
||||||
@ -454,17 +499,20 @@ Any git command accepting any <object> can also use the following
|
|||||||
symbolic notation:
|
symbolic notation:
|
||||||
|
|
||||||
HEAD::
|
HEAD::
|
||||||
indicates the head of the repository (ie the contents of
|
indicates the head of the current branch (i.e. the
|
||||||
`$GIT_DIR/HEAD`)
|
contents of `$GIT_DIR/HEAD`).
|
||||||
|
|
||||||
<tag>::
|
<tag>::
|
||||||
a valid tag 'name'+
|
a valid tag 'name'
|
||||||
(ie the contents of `$GIT_DIR/refs/tags/<tag>`)
|
(i.e. the contents of `$GIT_DIR/refs/tags/<tag>`).
|
||||||
|
|
||||||
<head>::
|
<head>::
|
||||||
a valid head 'name'+
|
a valid head 'name'
|
||||||
(ie the contents of `$GIT_DIR/refs/heads/<head>`)
|
(i.e. the contents of `$GIT_DIR/refs/heads/<head>`).
|
||||||
|
|
||||||
<snap>::
|
<snap>::
|
||||||
a valid snapshot 'name'+
|
a valid snapshot 'name'
|
||||||
(ie the contents of `$GIT_DIR/refs/snap/<snap>`)
|
(i.e. the contents of `$GIT_DIR/refs/snap/<snap>`).
|
||||||
|
|
||||||
|
|
||||||
File/Directory Structure
|
File/Directory Structure
|
||||||
@ -473,7 +521,7 @@ File/Directory Structure
|
|||||||
Please see link:repository-layout.html[repository layout] document.
|
Please see link:repository-layout.html[repository layout] document.
|
||||||
|
|
||||||
Higher level SCMs may provide and manage additional information in the
|
Higher level SCMs may provide and manage additional information in the
|
||||||
GIT_DIR.
|
`$GIT_DIR`.
|
||||||
|
|
||||||
|
|
||||||
Terminology
|
Terminology
|
||||||
@ -489,7 +537,7 @@ The git Repository
|
|||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
These environment variables apply to 'all' core git commands. Nb: it
|
These environment variables apply to 'all' core git commands. Nb: it
|
||||||
is worth noting that they may be used/overridden by SCMS sitting above
|
is worth noting that they may be used/overridden by SCMS sitting above
|
||||||
git so take care if using Cogito etc
|
git so take care if using Cogito etc.
|
||||||
|
|
||||||
'GIT_INDEX_FILE'::
|
'GIT_INDEX_FILE'::
|
||||||
This environment allows the specification of an alternate
|
This environment allows the specification of an alternate
|
||||||
@ -510,9 +558,9 @@ git so take care if using Cogito etc
|
|||||||
written to these directories.
|
written to these directories.
|
||||||
|
|
||||||
'GIT_DIR'::
|
'GIT_DIR'::
|
||||||
If the 'GIT_DIR' environment variable is set then it specifies
|
If the 'GIT_DIR' environment variable is set then it
|
||||||
a path to use instead of `./.git` for the base of the
|
specifies a path to use instead of the default `.git`
|
||||||
repository.
|
for the base of the repository.
|
||||||
|
|
||||||
git Commits
|
git Commits
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
@ -536,13 +584,18 @@ Discussion[[Discussion]]
|
|||||||
------------------------
|
------------------------
|
||||||
include::../README[]
|
include::../README[]
|
||||||
|
|
||||||
Author
|
Authors
|
||||||
------
|
-------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org> and the git-list <git@vger.kernel.org>.
|
* 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
|
Documentation
|
||||||
--------------
|
--------------
|
||||||
Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
|
The documentation for git suite was started by David Greaves
|
||||||
|
<david@dgreaves.com>, and later enhanced greatly by the
|
||||||
|
contributors on the git-list <git@vger.kernel.org>.
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
---
|
---
|
||||||
|
@ -20,7 +20,7 @@ hash::
|
|||||||
|
|
||||||
object database::
|
object database::
|
||||||
Stores a set of "objects", and an individial object is identified
|
Stores a set of "objects", and an individial object is identified
|
||||||
by its object name. The object usually live in $GIT_DIR/objects/.
|
by its object name. The objects usually live in `$GIT_DIR/objects/`.
|
||||||
|
|
||||||
blob object::
|
blob object::
|
||||||
Untyped object, e.g. the contents of a file.
|
Untyped object, e.g. the contents of a file.
|
||||||
@ -109,15 +109,15 @@ head::
|
|||||||
branch::
|
branch::
|
||||||
A non-cyclical graph of revisions, i.e. the complete history of
|
A non-cyclical graph of revisions, i.e. the complete history of
|
||||||
a particular revision, which is called the branch head. The
|
a particular revision, which is called the branch head. The
|
||||||
branch heads are stored in $GIT_DIR/refs/heads/.
|
branch heads are stored in `$GIT_DIR/refs/heads/`.
|
||||||
|
|
||||||
ref::
|
ref::
|
||||||
A 40-byte hex representation of a SHA1 pointing to a particular
|
A 40-byte hex representation of a SHA1 pointing to a particular
|
||||||
object. These may be stored in $GIT_DIR/refs/.
|
object. These may be stored in `$GIT_DIR/refs/`.
|
||||||
|
|
||||||
head ref::
|
head ref::
|
||||||
A ref pointing to a head. Often, this is abbreviated to "head".
|
A ref pointing to a head. Often, this is abbreviated to "head".
|
||||||
Head refs are stored in $GIT_DIR/refs/heads/.
|
Head refs are stored in `$GIT_DIR/refs/heads/`.
|
||||||
|
|
||||||
tree-ish::
|
tree-ish::
|
||||||
A ref pointing to either a commit object, a tree object, or a
|
A ref pointing to either a commit object, a tree object, or a
|
||||||
@ -125,7 +125,7 @@ tree-ish::
|
|||||||
|
|
||||||
ent::
|
ent::
|
||||||
Favorite synonym to "tree-ish" by some total geeks. See
|
Favorite synonym to "tree-ish" by some total geeks. See
|
||||||
http://en.wikipedia.org/wiki/Ent_(Middle-earth) for an in-depth
|
`http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth
|
||||||
explanation.
|
explanation.
|
||||||
|
|
||||||
tag object::
|
tag object::
|
||||||
@ -137,7 +137,7 @@ tag object::
|
|||||||
tag::
|
tag::
|
||||||
A ref pointing to a tag or commit object. In contrast to a head,
|
A ref pointing to a tag or commit object. In contrast to a head,
|
||||||
a tag is not changed by a commit. Tags (not tag objects) are
|
a tag is not changed by a commit. Tags (not tag objects) are
|
||||||
stored in $GIT_DIR/refs/tags/. A git tag has nothing to do with
|
stored in `$GIT_DIR/refs/tags/`. A git tag has nothing to do with
|
||||||
a Lisp tag (which is called object type in git's context).
|
a Lisp tag (which is called object type in git's context).
|
||||||
A tag is most typically used to mark a particular point in the
|
A tag is most typically used to mark a particular point in the
|
||||||
commit ancestry chain.
|
commit ancestry chain.
|
||||||
|
@ -111,6 +111,10 @@ Another use suggested on the mailing list is to use this hook to
|
|||||||
implement access control which is finer grained than the one
|
implement access control which is finer grained than the one
|
||||||
based on filesystem group.
|
based on filesystem group.
|
||||||
|
|
||||||
|
The standard output of this hook is sent to /dev/null; if you
|
||||||
|
want to report something to the git-send-pack on the other end,
|
||||||
|
you can redirect your output to your stderr.
|
||||||
|
|
||||||
post-update
|
post-update
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
@ -125,3 +129,7 @@ the outcome of `git-receive-pack`.
|
|||||||
The default post-update hook, when enabled, runs
|
The default post-update hook, when enabled, runs
|
||||||
`git-update-server-info` to keep the information used by dumb
|
`git-update-server-info` to keep the information used by dumb
|
||||||
transport up-to-date.
|
transport up-to-date.
|
||||||
|
|
||||||
|
The standard output of this hook is sent to /dev/null; if you
|
||||||
|
want to report something to the git-send-pack on the other end,
|
||||||
|
you can redirect your output to your stderr.
|
||||||
|
@ -40,10 +40,7 @@ So I started from master, made a bunch of edits, and committed:
|
|||||||
$ git checkout master
|
$ git checkout master
|
||||||
$ cd Documentation; ed git.txt ...
|
$ cd Documentation; ed git.txt ...
|
||||||
$ cd ..; git add Documentation/*.txt
|
$ cd ..; git add Documentation/*.txt
|
||||||
$ git commit -s -v
|
$ git commit -s
|
||||||
|
|
||||||
NOTE. The -v flag to commit is a handy way to make sure that
|
|
||||||
your additions are not introducing bogusly formatted lines.
|
|
||||||
|
|
||||||
After the commit, the ancestry graph would look like this:
|
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.
|
Let's go back to the earlier picture, with different labels.
|
||||||
|
|
||||||
You, as an individual developer, cloned upstream repository and
|
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
|
*your "master" head
|
||||||
upstream --> #1 --> #2 --> #3
|
upstream --> #1 --> #2 --> #3
|
||||||
|
@ -10,7 +10,7 @@ The pages under http://www.kernel.org/pub/software/scm/git/docs/
|
|||||||
are built from Documentation/ directory of the git.git project
|
are built from Documentation/ directory of the git.git project
|
||||||
and needed to be kept up-to-date. The www.kernel.org/ servers
|
and needed to be kept up-to-date. The www.kernel.org/ servers
|
||||||
are mirrored and I was told that the origin of the mirror is on
|
are mirrored and I was told that the origin of the mirror is on
|
||||||
the machine master.kernel.org, on which I was given an account
|
the machine $some.kernel.org, on which I was given an account
|
||||||
when I took over git maintainership from Linus.
|
when I took over git maintainership from Linus.
|
||||||
|
|
||||||
The directories relevant to this how-to are these two:
|
The directories relevant to this how-to are these two:
|
||||||
@ -63,7 +63,7 @@ like this:
|
|||||||
EOF
|
EOF
|
||||||
$ chmod +x /pub/scm/git/git.git/hooks/post-update
|
$ chmod +x /pub/scm/git/git.git/hooks/post-update
|
||||||
|
|
||||||
There are three things worth mentioning:
|
There are four things worth mentioning:
|
||||||
|
|
||||||
- The update-hook is run after the repository accepts a "git
|
- The update-hook is run after the repository accepts a "git
|
||||||
push", under my user privilege. It is given the full names
|
push", under my user privilege. It is given the full names
|
||||||
@ -77,6 +77,10 @@ There are three things worth mentioning:
|
|||||||
pull" it does into $HOME/doc-git/docgen/ repository would not
|
pull" it does into $HOME/doc-git/docgen/ repository would not
|
||||||
work correctly.
|
work correctly.
|
||||||
|
|
||||||
|
- The stdout of update hook script is not connected to git
|
||||||
|
push; I run the heavy part of the command inside "at", to
|
||||||
|
receive the execution report via e-mail.
|
||||||
|
|
||||||
- This is still crude and does not protect against simultaneous
|
- This is still crude and does not protect against simultaneous
|
||||||
make invocations stomping on each other. I would need to add
|
make invocations stomping on each other. I would need to add
|
||||||
some locking mechanism for this.
|
some locking mechanism for this.
|
||||||
|
172
Documentation/howto/update-hook-example.txt
Normal file
172
Documentation/howto/update-hook-example.txt
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
From: Junio C Hamano <junkio@cox.net> and Carl Baldwin <cnb@fc.hp.com>
|
||||||
|
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 you can use something
|
||||||
|
like this as your hooks/update script.
|
||||||
|
|
||||||
|
[jc: editorial note. This is a much improved version by Carl
|
||||||
|
since I posted the original outline]
|
||||||
|
|
||||||
|
-- >8 -- beginning of script -- >8 --
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
umask 002
|
||||||
|
|
||||||
|
# If you are having trouble with this access control hook script
|
||||||
|
# you can try setting this to true. It will tell you exactly
|
||||||
|
# why a user is being allowed/denied access.
|
||||||
|
|
||||||
|
verbose=false
|
||||||
|
|
||||||
|
# Default shell globbing messes things up downstream
|
||||||
|
GLOBIGNORE=*
|
||||||
|
|
||||||
|
function grant {
|
||||||
|
$verbose && echo >&2 "-Grant- $1"
|
||||||
|
echo grant
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function deny {
|
||||||
|
$verbose && echo >&2 "-Deny- $1"
|
||||||
|
echo deny
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function info {
|
||||||
|
$verbose && echo >&2 "-Info- $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Implement generic branch and tag policies.
|
||||||
|
# - Tags should not be updated once created.
|
||||||
|
# - Branches should only be fast-forwarded.
|
||||||
|
case "$1" in
|
||||||
|
refs/tags/*)
|
||||||
|
[ -f "$GIT_DIR/$1" ] &&
|
||||||
|
deny >/dev/null "You can't overwrite an existing tag"
|
||||||
|
;;
|
||||||
|
refs/heads/*)
|
||||||
|
# No rebasing or rewinding
|
||||||
|
if expr "$2" : '0*$' >/dev/null; then
|
||||||
|
info "The branch '$1' is new..."
|
||||||
|
else
|
||||||
|
# updating -- make sure it is a fast forward
|
||||||
|
mb=$(git-merge-base "$2" "$3")
|
||||||
|
case "$mb,$2" in
|
||||||
|
"$2,$mb") info "Update is fast-forward" ;;
|
||||||
|
*) deny >/dev/null "This is not a fast-forward update." ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
deny >/dev/null \
|
||||||
|
"Branch is not under refs/heads or refs/tags. What are you trying to do?"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Implement per-branch controls based on username
|
||||||
|
allowed_users_file=$GIT_DIR/info/allowed-users
|
||||||
|
username=$(id -u -n)
|
||||||
|
info "The user is: '$username'"
|
||||||
|
|
||||||
|
if [ -f "$allowed_users_file" ]; then
|
||||||
|
rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' |
|
||||||
|
while read head_pattern user_patterns; do
|
||||||
|
matchlen=$(expr "$1" : "$head_pattern")
|
||||||
|
if [ "$matchlen" == "${#1}" ]; then
|
||||||
|
info "Found matching head pattern: '$head_pattern'"
|
||||||
|
for user_pattern in $user_patterns; do
|
||||||
|
info "Checking user: '$username' against pattern: '$user_pattern'"
|
||||||
|
matchlen=$(expr "$username" : "$user_pattern")
|
||||||
|
if [ "$matchlen" == "${#username}" ]; then
|
||||||
|
grant "Allowing user: '$username' with pattern: '$user_pattern'"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
deny "The user is not in the access list for this branch"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
)
|
||||||
|
case "$rc" in
|
||||||
|
grant) grant >/dev/null "Granting access based on $allowed_users_file" ;;
|
||||||
|
deny) deny >/dev/null "Denying access based on $allowed_users_file" ;;
|
||||||
|
*) ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
allowed_groups_file=$GIT_DIR/info/allowed-groups
|
||||||
|
groups=$(id -G -n)
|
||||||
|
info "The user belongs to the following groups:"
|
||||||
|
info "'$groups'"
|
||||||
|
|
||||||
|
if [ -f "$allowed_groups_file" ]; then
|
||||||
|
rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' |
|
||||||
|
while read head_pattern group_patterns; do
|
||||||
|
matchlen=$(expr "$1" : "$head_pattern")
|
||||||
|
if [ "$matchlen" == "${#1}" ]; then
|
||||||
|
info "Found matching head pattern: '$head_pattern'"
|
||||||
|
for group_pattern in $group_patterns; do
|
||||||
|
for groupname in $groups; do
|
||||||
|
info "Checking group: '$groupname' against pattern: '$group_pattern'"
|
||||||
|
matchlen=$(expr "$groupname" : "$group_pattern")
|
||||||
|
if [ "$matchlen" == "${#groupname}" ]; then
|
||||||
|
grant "Allowing group: '$groupname' with pattern: '$group_pattern'"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
deny "None of the user's groups are in the access list for this branch"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
)
|
||||||
|
case "$rc" in
|
||||||
|
grant) grant >/dev/null "Granting access based on $allowed_groups_file" ;;
|
||||||
|
deny) deny >/dev/null "Denying access based on $allowed_groups_file" ;;
|
||||||
|
*) ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
deny >/dev/null "There are no more rules to check. Denying access"
|
||||||
|
|
||||||
|
-- >8 -- end of script -- >8 --
|
||||||
|
|
||||||
|
This uses two files, $GIT_DIR/info/allowed-users and
|
||||||
|
allowed-groups, to describe which heads can be pushed into by
|
||||||
|
whom. The format of each file would look like this:
|
||||||
|
|
||||||
|
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 JC can
|
||||||
|
do master branch and make versioned tags. And anybody can do
|
||||||
|
tmp/blah branches.
|
||||||
|
|
||||||
|
------------
|
@ -31,7 +31,7 @@ test tree and then pull to the release tree as that would leave trivial
|
|||||||
patches blocked in the test tree waiting for complex changes to accumulate
|
patches blocked in the test tree waiting for complex changes to accumulate
|
||||||
enough test time to graduate.
|
enough test time to graduate.
|
||||||
|
|
||||||
Back in the BitKeeper days I achieved this my creating small forests of
|
Back in the BitKeeper days I achieved this by creating small forests of
|
||||||
temporary trees, one tree for each logical grouping of patches, and then
|
temporary trees, one tree for each logical grouping of patches, and then
|
||||||
pulling changes from these trees first to the test tree, and then to the
|
pulling changes from these trees first to the test tree, and then to the
|
||||||
release tree. At first I replicated this in GIT, but then I realised
|
release tree. At first I replicated this in GIT, but then I realised
|
||||||
@ -42,7 +42,7 @@ So here is the step-by-step guide how this all works for me.
|
|||||||
|
|
||||||
First create your work tree by cloning Linus's public tree:
|
First create your work tree by cloning Linus's public tree:
|
||||||
|
|
||||||
$ git clone rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
|
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
|
||||||
|
|
||||||
Change directory into the cloned tree you just created
|
Change directory into the cloned tree you just created
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ Set up a remotes file so that you can fetch the latest from Linus' master
|
|||||||
branch into a local branch named "linus":
|
branch into a local branch named "linus":
|
||||||
|
|
||||||
$ cat > .git/remotes/linus
|
$ cat > .git/remotes/linus
|
||||||
URL: rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
|
URL: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
|
||||||
Pull: master:linus
|
Pull: master:linus
|
||||||
^D
|
^D
|
||||||
|
|
||||||
|
@ -11,6 +11,6 @@
|
|||||||
Use the given merge strategy; can be supplied more than
|
Use the given merge strategy; can be supplied more than
|
||||||
once to specify them in the order they should be tried.
|
once to specify them in the order they should be tried.
|
||||||
If there is no `-s` option, a built-in list of strategies
|
If there is no `-s` option, a built-in list of strategies
|
||||||
is used instead (`git-merge-resolve` when merging a single
|
is used instead (`git-merge-recursive` when merging a single
|
||||||
head, `git-merge-octopus` otherwise).
|
head, `git-merge-octopus` otherwise).
|
||||||
|
|
||||||
|
@ -6,27 +6,27 @@ resolve::
|
|||||||
and another branch you pulled from) using 3-way merge
|
and another branch you pulled from) using 3-way merge
|
||||||
algorithm. It tries to carefully detect criss-cross
|
algorithm. It tries to carefully detect criss-cross
|
||||||
merge ambiguities and is considered generally safe and
|
merge ambiguities and is considered generally safe and
|
||||||
fast. This is the default merge strategy when pulling
|
fast.
|
||||||
one branch.
|
|
||||||
|
|
||||||
recursive::
|
recursive::
|
||||||
This can only resolve two heads using 3-way merge
|
This can only resolve two heads using 3-way merge
|
||||||
algorithm. When there are more than one common
|
algorithm. When there are more than one common
|
||||||
ancestors that can be used for 3-way merge, it creates a
|
ancestors that can be used for 3-way merge, it creates a
|
||||||
merged tree of the common ancestores and uses that as
|
merged tree of the common ancestors and uses that as
|
||||||
the reference tree for the 3-way merge. This has been
|
the reference tree for the 3-way merge. This has been
|
||||||
reported to result in fewer merge conflicts without
|
reported to result in fewer merge conflicts without
|
||||||
causing mis-merges by tests done on actual merge commits
|
causing mis-merges by tests done on actual merge commits
|
||||||
taken from Linux 2.6 kernel development history.
|
taken from Linux 2.6 kernel development history.
|
||||||
Additionally this can detect and handle merges involving
|
Additionally this can detect and handle merges involving
|
||||||
renames.
|
renames. This is the default merge strategy when
|
||||||
|
pulling or merging one branch.
|
||||||
|
|
||||||
octopus::
|
octopus::
|
||||||
This resolves more than two-head case, but refuses to do
|
This resolves more than two-head case, but refuses to do
|
||||||
complex merge that needs manual resolution. It is
|
complex merge that needs manual resolution. It is
|
||||||
primarily meant to be used for bundling topic branch
|
primarily meant to be used for bundling topic branch
|
||||||
heads together. This is the default merge strategy when
|
heads together. This is the default merge strategy when
|
||||||
pulling more than one branch.
|
pulling or merging more than one branches.
|
||||||
|
|
||||||
ours::
|
ours::
|
||||||
This resolves any number of heads, but the result of the
|
This resolves any number of heads, but the result of the
|
||||||
|
@ -5,11 +5,31 @@
|
|||||||
to name the remote repository:
|
to name the remote repository:
|
||||||
+
|
+
|
||||||
===============================================================
|
===============================================================
|
||||||
- Rsync URL: rsync://remote.machine/path/to/repo.git/
|
- rsync://host.xz/path/to/repo.git/
|
||||||
- HTTP(s) URL: http://remote.machine/path/to/repo.git/
|
- http://host.xz/path/to/repo.git/
|
||||||
- git URL: git://remote.machine/path/to/repo.git/
|
- https://host.xz/path/to/repo.git/
|
||||||
- ssh URL: remote.machine:/path/to/repo.git/
|
- git://host.xz/path/to/repo.git/
|
||||||
- Local directory: /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
|
In addition to the above, as a short-hand, the name of a
|
||||||
@ -93,7 +113,7 @@ on the remote branch, merge it into your development branch with
|
|||||||
`git pull . remote-B`, while you are on `my-B` branch.
|
`git pull . remote-B`, while you are on `my-B` branch.
|
||||||
The common `Pull: master:origin` mapping of a remote `master`
|
The common `Pull: master:origin` mapping of a remote `master`
|
||||||
branch to a local `origin` branch, which is then merged to a
|
branch to a local `origin` branch, which is then merged to a
|
||||||
ocal development branch, again typically named `master`, is made
|
local development branch, again typically named `master`, is made
|
||||||
when you run `git clone` for you to follow this pattern.
|
when you run `git clone` for you to follow this pattern.
|
||||||
+
|
+
|
||||||
[NOTE]
|
[NOTE]
|
||||||
|
@ -42,7 +42,6 @@ sub no_spaces ($) {
|
|||||||
|
|
||||||
print 'GIT Glossary
|
print 'GIT Glossary
|
||||||
============
|
============
|
||||||
Aug 2005
|
|
||||||
|
|
||||||
This list is sorted alphabetically:
|
This list is sorted alphabetically:
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Pack transfer protocols
|
||||||
|
=======================
|
||||||
|
|
||||||
There are two Pack push-pull protocols.
|
There are two Pack push-pull protocols.
|
||||||
|
|
||||||
upload-pack (S) | fetch/clone-pack (C) protocol:
|
upload-pack (S) | fetch/clone-pack (C) protocol:
|
@ -18,7 +18,20 @@ doing.
|
|||||||
The core git is often called "plumbing", with the prettier user
|
The core git is often called "plumbing", with the prettier user
|
||||||
interfaces on top of it called "porcelain". You may not want to use the
|
interfaces on top of it called "porcelain". You may not want to use the
|
||||||
plumbing directly very often, but it can be good to know what the
|
plumbing directly very often, but it can be good to know what the
|
||||||
plumbing does for when the porcelain isn't flushing...
|
plumbing does for when the porcelain isn't flushing.
|
||||||
|
|
||||||
|
The material presented here often goes deep describing how things
|
||||||
|
work internally. If you are mostly interested in using git as a
|
||||||
|
SCM, you can skip them during your first pass.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
And those "too deep" descriptions are often marked as Note.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
If you are already familiar with another version control system,
|
||||||
|
like CVS, you may want to take a look at
|
||||||
|
link:everyday.html[Everyday GIT in 20 commands or so] first
|
||||||
|
before reading this.
|
||||||
|
|
||||||
|
|
||||||
Creating a git repository
|
Creating a git repository
|
||||||
@ -252,6 +265,17 @@ tree. That's very useful.
|
|||||||
A common shorthand for `git-diff-files -p` is to just write `git
|
A common shorthand for `git-diff-files -p` is to just write `git
|
||||||
diff`, which will do the same thing.
|
diff`, which will do the same thing.
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git diff
|
||||||
|
diff --git a/hello b/hello
|
||||||
|
index 557db03..263414f 100644
|
||||||
|
--- a/hello
|
||||||
|
+++ b/hello
|
||||||
|
@@ -1 +1,2 @@
|
||||||
|
Hello World
|
||||||
|
+It's a new day for git
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
Committing git state
|
Committing git state
|
||||||
--------------------
|
--------------------
|
||||||
@ -898,9 +922,8 @@ file, which had no differences in the `mybranch` branch), and say:
|
|||||||
fatal: Merge requires file-level merging
|
fatal: Merge requires file-level merging
|
||||||
Nope.
|
Nope.
|
||||||
...
|
...
|
||||||
merge: warning: conflicts during merge
|
Auto-merging hello
|
||||||
ERROR: Merge conflict in hello.
|
CONFLICT (content): Merge conflict in hello
|
||||||
fatal: merge program failed
|
|
||||||
Automatic merge failed/prevented; fix up by hand
|
Automatic merge failed/prevented; fix up by hand
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
@ -942,10 +965,10 @@ environment, is `git show-branch`.
|
|||||||
|
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
$ git show-branch master mybranch
|
$ git show-branch master mybranch
|
||||||
* [master] Merged "mybranch" changes.
|
* [master] Merge work in mybranch
|
||||||
! [mybranch] Some work.
|
! [mybranch] Some work.
|
||||||
--
|
--
|
||||||
+ [master] Merged "mybranch" changes.
|
+ [master] Merge work in mybranch
|
||||||
++ [mybranch] Some work.
|
++ [mybranch] Some work.
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
@ -998,10 +1021,10 @@ looks like, or run `show-branch`, which tells you this.
|
|||||||
|
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
$ git show-branch master mybranch
|
$ git show-branch master mybranch
|
||||||
! [master] Merged "mybranch" changes.
|
! [master] Merge work in mybranch
|
||||||
* [mybranch] Merged "mybranch" changes.
|
* [mybranch] Merge work in mybranch
|
||||||
--
|
--
|
||||||
++ [master] Merged "mybranch" changes.
|
++ [master] Merge work in mybranch
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@ -1068,9 +1091,10 @@ lacks and transfers (close to) minimum set of objects.
|
|||||||
HTTP(S)::
|
HTTP(S)::
|
||||||
`http://remote.machine/path/to/repo.git/`
|
`http://remote.machine/path/to/repo.git/`
|
||||||
+
|
+
|
||||||
HTTP and HTTPS transport are used only for downloading. They
|
Downloader from http and https URL
|
||||||
first obtain the topmost commit object name from the remote site
|
first obtains the topmost commit object name from the remote site
|
||||||
by looking at `repo.git/info/refs` file, tries to obtain the
|
by looking at the specified refname under `repo.git/refs/` directory,
|
||||||
|
and then tries to obtain the
|
||||||
commit object by downloading from `repo.git/objects/xx/xxx\...`
|
commit object by downloading from `repo.git/objects/xx/xxx\...`
|
||||||
using the object name of that commit object. Then it reads the
|
using the object name of that commit object. Then it reads the
|
||||||
commit object to find out its parent commits and the associate
|
commit object to find out its parent commits and the associate
|
||||||
@ -1081,7 +1105,9 @@ sometimes also called 'commit walkers'.
|
|||||||
The 'commit walkers' are sometimes also called 'dumb
|
The 'commit walkers' are sometimes also called 'dumb
|
||||||
transports', because they do not require any git aware smart
|
transports', because they do not require any git aware smart
|
||||||
server like git Native transport does. Any stock HTTP server
|
server like git Native transport does. Any stock HTTP server
|
||||||
would suffice.
|
that does not even support directory index would suffice. But
|
||||||
|
you must prepare your repository with `git-update-server-info`
|
||||||
|
to help dumb transport downloaders.
|
||||||
+
|
+
|
||||||
There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload`
|
There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload`
|
||||||
programs, which are 'commit walkers'; they outlived their
|
programs, which are 'commit walkers'; they outlived their
|
||||||
@ -1283,26 +1309,27 @@ fatal: merge program failed
|
|||||||
|
|
||||||
`git-merge-one-file` script is called with parameters to
|
`git-merge-one-file` script is called with parameters to
|
||||||
describe those three versions, and is responsible to leave the
|
describe those three versions, and is responsible to leave the
|
||||||
merge results in the working tree and register it in the index
|
merge results in the working tree.
|
||||||
file. It is a fairly straightforward shell script, and
|
It is a fairly straightforward shell script, and
|
||||||
eventually calls `merge` program from RCS suite to perform the
|
eventually calls `merge` program from RCS suite to perform a
|
||||||
file-level 3-way merge. In this case, `merge` detects
|
file-level 3-way merge. In this case, `merge` detects
|
||||||
conflicts, and the merge result with conflict marks is left in
|
conflicts, and the merge result with conflict marks is left in
|
||||||
the working tree, while the index file is updated with the
|
the working tree.. This can be seen if you run `ls-files
|
||||||
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:
|
--stage` again at this point:
|
||||||
|
|
||||||
------------
|
------------
|
||||||
$ git-ls-files --stage
|
$ git-ls-files --stage
|
||||||
100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example
|
100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example
|
||||||
100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 0 hello
|
100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1 hello
|
||||||
|
100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2 hello
|
||||||
|
100644 cc44c73eb783565da5831b4d820c962954019b69 3 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
|
This is the state of the index file and the working file after
|
||||||
`git merge` returns control back to you, leaving the conflicting
|
`git merge` returns control back to you, leaving the conflicting
|
||||||
merge for you to resolve.
|
merge for you to resolve. Notice that the path `hello` is still
|
||||||
|
unmerged, and what you see with `git diff` at this point is
|
||||||
|
differences since stage 2 (i.e. your version).
|
||||||
|
|
||||||
|
|
||||||
Publishing your work
|
Publishing your work
|
||||||
@ -1493,12 +1520,13 @@ A recommended workflow for a "project lead" goes like this:
|
|||||||
2. Prepare a public repository accessible to others.
|
2. Prepare a public repository accessible to others.
|
||||||
+
|
+
|
||||||
If other people are pulling from your repository over dumb
|
If other people are pulling from your repository over dumb
|
||||||
transport protocols, you need to keep this repository 'dumb
|
transport protocols (HTTP), you need to keep this repository
|
||||||
transport friendly'. After `git init-db`,
|
'dumb transport friendly'. After `git init-db`,
|
||||||
`$GIT_DIR/hooks/post-update` copied from the standard templates
|
`$GIT_DIR/hooks/post-update` copied from the standard templates
|
||||||
would contain a call to `git-update-server-info` but the
|
would contain a call to `git-update-server-info` but the
|
||||||
`post-update` hook itself is disabled by default -- enable it
|
`post-update` hook itself is disabled by default -- enable it
|
||||||
with `chmod +x post-update`.
|
with `chmod +x post-update`. This makes sure `git-update-server-info`
|
||||||
|
keeps the necessary files up-to-date.
|
||||||
|
|
||||||
3. Push into the public repository from your primary
|
3. Push into the public repository from your primary
|
||||||
repository.
|
repository.
|
||||||
@ -1534,7 +1562,10 @@ on that project and has an own "public repository" goes like this:
|
|||||||
the "project lead" person does.
|
the "project lead" person does.
|
||||||
|
|
||||||
3. Copy over the packed files from "project lead" public
|
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
|
4. Push into the public repository from your primary
|
||||||
repository. Run `git repack`, and possibly `git prune` if the
|
repository. Run `git repack`, and possibly `git prune` if the
|
||||||
@ -1594,7 +1625,9 @@ cooperation you are probably more familiar with as well.
|
|||||||
For this, set up a public repository on a machine that is
|
For this, set up a public repository on a machine that is
|
||||||
reachable via SSH by people with "commit privileges". Put the
|
reachable via SSH by people with "commit privileges". Put the
|
||||||
committers in the same user group and make the repository
|
committers in the same user group and make the repository
|
||||||
writable by that group.
|
writable by that group. Make sure their umasks are set up to
|
||||||
|
allow group members to write into directories other members
|
||||||
|
have created.
|
||||||
|
|
||||||
You, as an individual committer, then:
|
You, as an individual committer, then:
|
||||||
|
|
||||||
@ -1634,14 +1667,49 @@ fast forward. You need to pull and merge those other changes
|
|||||||
back before you push your work when it happens.
|
back before you push your work when it happens.
|
||||||
|
|
||||||
|
|
||||||
|
Advanced Shared Repository Management
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Being able to push into a shared repository means being able to
|
||||||
|
write into it. If your developers are coming over the network,
|
||||||
|
this means you, as the repository administrator, need to give
|
||||||
|
each of them an SSH access to the shared repository machine.
|
||||||
|
|
||||||
|
In some cases, though, you may not want to give a normal shell
|
||||||
|
account to them, but want to restrict them to be able to only
|
||||||
|
do `git push` into the repository and nothing else.
|
||||||
|
|
||||||
|
You can achieve this by setting the login shell of your
|
||||||
|
developers on the shared repository host to `git-shell` program.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
Most likely you would also need to list `git-shell` program in
|
||||||
|
`/etc/shells` file.
|
||||||
|
|
||||||
|
This restricts the set of commands that can be run from incoming
|
||||||
|
SSH connection for these users to only `receive-pack` and
|
||||||
|
`upload-pack`, so the only thing they can do are `git fetch` and
|
||||||
|
`git push`.
|
||||||
|
|
||||||
|
You still need to create UNIX user accounts for each developer,
|
||||||
|
and put them in the same group. Make sure that the repository
|
||||||
|
shared among these developers is writable by that group.
|
||||||
|
|
||||||
|
You can implement finer grained branch policies using update
|
||||||
|
hooks. There is a document ("control access to branches") in
|
||||||
|
Documentation/howto by Carl Baldwin and JC outlining how to (1)
|
||||||
|
limit access to branch per user, (2) forbid overwriting existing
|
||||||
|
tags.
|
||||||
|
|
||||||
|
|
||||||
Bundling your work together
|
Bundling your work together
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
It is likely that you will be working on more than one thing at
|
It is likely that you will be working on more than one thing at
|
||||||
a time. It is easy to use those more-or-less independent tasks
|
a time. It is easy to manage those more-or-less independent tasks
|
||||||
using branches with git.
|
using branches with git.
|
||||||
|
|
||||||
We have already seen how branches work in a previous example,
|
We have already seen how branches work previously,
|
||||||
with "fun and work" example using two branches. The idea is the
|
with "fun and work" example using two branches. The idea is the
|
||||||
same if there are more than two branches. Let's say you started
|
same if there are more than two branches. Let's say you started
|
||||||
out from "master" head, and have some new code in the "master"
|
out from "master" head, and have some new code in the "master"
|
||||||
|
3
INSTALL
3
INSTALL
@ -87,3 +87,6 @@ Issues of note:
|
|||||||
have all the libraries/tools needed, or you may have
|
have all the libraries/tools needed, or you may have
|
||||||
necessary libraries at unusual locations. Please look at the
|
necessary libraries at unusual locations. Please look at the
|
||||||
top of the Makefile to see what can be adjusted for your needs.
|
top of the Makefile to see what can be adjusted for your needs.
|
||||||
|
You can place local settings in config.mak and the Makefile
|
||||||
|
will include them. Note that config.mak is not distributed;
|
||||||
|
the name is reserved for local settings.
|
||||||
|
186
Makefile
186
Makefile
@ -1,3 +1,6 @@
|
|||||||
|
# The default target of this Makefile is...
|
||||||
|
all:
|
||||||
|
|
||||||
# Define MOZILLA_SHA1 environment variable when running make to make use of
|
# Define MOZILLA_SHA1 environment variable when running make to make use of
|
||||||
# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
|
# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
|
||||||
# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
|
# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
|
||||||
@ -18,6 +21,8 @@
|
|||||||
#
|
#
|
||||||
# Define NO_STRCASESTR if you don't have strcasestr.
|
# Define NO_STRCASESTR if you don't have strcasestr.
|
||||||
#
|
#
|
||||||
|
# Define NO_SETENV if you don't have setenv in the C library.
|
||||||
|
#
|
||||||
# Define PPC_SHA1 environment variable when running make to make use of
|
# Define PPC_SHA1 environment variable when running make to make use of
|
||||||
# a bundled SHA1 routine optimized for PowerPC.
|
# a bundled SHA1 routine optimized for PowerPC.
|
||||||
#
|
#
|
||||||
@ -50,12 +55,14 @@
|
|||||||
# Define USE_STDEV below if you want git to care about the underlying device
|
# 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.
|
# change being considered an inode change from the update-cache perspective.
|
||||||
|
|
||||||
GIT_VERSION = 0.99.9h
|
GIT_VERSION = 1.0.0
|
||||||
|
|
||||||
# CFLAGS is for the users to override from the command line.
|
# CFLAGS and LDFLAGS are for the users to override from the command line.
|
||||||
|
|
||||||
CFLAGS = -g -O2 -Wall
|
CFLAGS = -g -O2 -Wall
|
||||||
|
LDFLAGS =
|
||||||
ALL_CFLAGS = $(CFLAGS)
|
ALL_CFLAGS = $(CFLAGS)
|
||||||
|
ALL_LDFLAGS = $(LDFLAGS)
|
||||||
|
|
||||||
prefix = $(HOME)
|
prefix = $(HOME)
|
||||||
bindir = $(prefix)/bin
|
bindir = $(prefix)/bin
|
||||||
@ -82,28 +89,33 @@ SCRIPT_SH = \
|
|||||||
git-cherry.sh git-clone.sh git-commit.sh \
|
git-cherry.sh git-clone.sh git-commit.sh \
|
||||||
git-count-objects.sh git-diff.sh git-fetch.sh \
|
git-count-objects.sh git-diff.sh git-fetch.sh \
|
||||||
git-format-patch.sh git-log.sh git-ls-remote.sh \
|
git-format-patch.sh git-log.sh git-ls-remote.sh \
|
||||||
git-merge-one-file.sh git-octopus.sh git-parse-remote.sh \
|
git-merge-one-file.sh git-parse-remote.sh \
|
||||||
git-prune.sh git-pull.sh git-push.sh git-rebase.sh \
|
git-prune.sh git-pull.sh git-push.sh git-rebase.sh \
|
||||||
git-repack.sh git-request-pull.sh git-reset.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-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-applymbox.sh git-applypatch.sh git-am.sh \
|
||||||
git-merge.sh git-merge-stupid.sh git-merge-octopus.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
|
git-lost-found.sh
|
||||||
|
|
||||||
SCRIPT_PERL = \
|
SCRIPT_PERL = \
|
||||||
git-archimport.perl git-cvsimport.perl git-relink.perl \
|
git-archimport.perl git-cvsimport.perl git-relink.perl \
|
||||||
git-rename.perl git-shortlog.perl git-fmt-merge-msg.perl \
|
git-shortlog.perl git-fmt-merge-msg.perl \
|
||||||
git-svnimport.perl git-mv.perl git-cvsexportcommit.perl
|
git-svnimport.perl git-mv.perl git-cvsexportcommit.perl
|
||||||
|
|
||||||
SCRIPT_PYTHON = \
|
SCRIPT_PYTHON = \
|
||||||
git-merge-recursive.py
|
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.
|
# The ones that do not have to link with lcrypto nor lz.
|
||||||
SIMPLE_PROGRAMS = \
|
SIMPLE_PROGRAMS = \
|
||||||
git-get-tar-commit-id$X git-mailinfo$X git-mailsplit$X \
|
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
|
# ... and all the rest
|
||||||
PROGRAMS = \
|
PROGRAMS = \
|
||||||
@ -123,32 +135,34 @@ PROGRAMS = \
|
|||||||
git-unpack-objects$X git-update-index$X git-update-server-info$X \
|
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-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-update-ref$X git-symbolic-ref$X git-check-ref-format$X \
|
||||||
git-name-rev$X git-pack-redundant$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
|
# Backward compatibility -- to be removed after 1.0
|
||||||
PROGRAMS += git-ssh-pull$X git-ssh-push$X
|
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 = \
|
PYMODULES = \
|
||||||
gitMergeCommon.py
|
gitMergeCommon.py
|
||||||
|
|
||||||
ifdef WITH_OWN_SUBPROCESS_PY
|
|
||||||
PYMODULES += compat/subprocess.py
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef WITH_SEND_EMAIL
|
|
||||||
SCRIPT_PERL += git-send-email.perl
|
|
||||||
else
|
|
||||||
GIT_LIST_TWEAK += -e '/^send-email$$/d'
|
|
||||||
endif
|
|
||||||
|
|
||||||
LIB_FILE=libgit.a
|
LIB_FILE=libgit.a
|
||||||
|
|
||||||
LIB_H = \
|
LIB_H = \
|
||||||
blob.h cache.h commit.h count-delta.h csum-file.h delta.h \
|
blob.h cache.h commit.h count-delta.h csum-file.h delta.h \
|
||||||
diff.h epoch.h object.h pack.h pkt-line.h quote.h refs.h \
|
diff.h epoch.h object.h pack.h pkt-line.h quote.h refs.h \
|
||||||
run-command.h strbuf.h tag.h tree.h
|
run-command.h strbuf.h tag.h tree.h git-compat-util.h
|
||||||
|
|
||||||
DIFF_OBJS = \
|
DIFF_OBJS = \
|
||||||
diff.o diffcore-break.o diffcore-order.o diffcore-pathspec.o \
|
diff.o diffcore-break.o diffcore-order.o diffcore-pathspec.o \
|
||||||
@ -161,6 +175,7 @@ LIB_OBJS = \
|
|||||||
quote.o read-cache.o refs.o run-command.o \
|
quote.o read-cache.o refs.o run-command.o \
|
||||||
server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
|
server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
|
||||||
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
|
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
|
||||||
|
fetch-clone.o \
|
||||||
$(DIFF_OBJS)
|
$(DIFF_OBJS)
|
||||||
|
|
||||||
LIBS = $(LIB_FILE)
|
LIBS = $(LIB_FILE)
|
||||||
@ -182,14 +197,17 @@ shellquote = '$(call shq,$(1))'
|
|||||||
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||||
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
|
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
|
||||||
uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
|
uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
|
||||||
|
uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
|
||||||
|
|
||||||
ifeq ($(uname_S),Darwin)
|
ifeq ($(uname_S),Darwin)
|
||||||
NEEDS_SSL_WITH_CRYPTO = YesPlease
|
NEEDS_SSL_WITH_CRYPTO = YesPlease
|
||||||
NEEDS_LIBICONV = YesPlease
|
NEEDS_LIBICONV = YesPlease
|
||||||
## fink
|
## fink
|
||||||
ALL_CFLAGS += -I/sw/include -L/sw/lib
|
ALL_CFLAGS += -I/sw/include
|
||||||
|
ALL_LDFLAGS += -L/sw/lib
|
||||||
## darwinports
|
## darwinports
|
||||||
ALL_CFLAGS += -I/opt/local/include -L/opt/local/lib
|
ALL_CFLAGS += -I/opt/local/include
|
||||||
|
ALL_LDFLAGS += -L/opt/local/lib
|
||||||
endif
|
endif
|
||||||
ifeq ($(uname_S),SunOS)
|
ifeq ($(uname_S),SunOS)
|
||||||
NEEDS_SOCKET = YesPlease
|
NEEDS_SOCKET = YesPlease
|
||||||
@ -197,6 +215,9 @@ ifeq ($(uname_S),SunOS)
|
|||||||
NEEDS_LIBICONV = YesPlease
|
NEEDS_LIBICONV = YesPlease
|
||||||
SHELL_PATH = /bin/bash
|
SHELL_PATH = /bin/bash
|
||||||
NO_STRCASESTR = YesPlease
|
NO_STRCASESTR = YesPlease
|
||||||
|
ifeq ($(uname_R),5.8)
|
||||||
|
NO_SETENV = YesPlease
|
||||||
|
endif
|
||||||
INSTALL = ginstall
|
INSTALL = ginstall
|
||||||
TAR = gtar
|
TAR = gtar
|
||||||
ALL_CFLAGS += -D__EXTENSIONS__
|
ALL_CFLAGS += -D__EXTENSIONS__
|
||||||
@ -204,6 +225,10 @@ endif
|
|||||||
ifeq ($(uname_O),Cygwin)
|
ifeq ($(uname_O),Cygwin)
|
||||||
NO_STRCASESTR = YesPlease
|
NO_STRCASESTR = YesPlease
|
||||||
NEEDS_LIBICONV = 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
|
NO_IPV6 = YesPlease
|
||||||
X = .exe
|
X = .exe
|
||||||
ALL_CFLAGS += -DUSE_SYMLINK_HEAD=0
|
ALL_CFLAGS += -DUSE_SYMLINK_HEAD=0
|
||||||
@ -211,7 +236,17 @@ endif
|
|||||||
ifeq ($(uname_S),OpenBSD)
|
ifeq ($(uname_S),OpenBSD)
|
||||||
NO_STRCASESTR = YesPlease
|
NO_STRCASESTR = YesPlease
|
||||||
NEEDS_LIBICONV = YesPlease
|
NEEDS_LIBICONV = YesPlease
|
||||||
ALL_CFLAGS += -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
|
||||||
|
ifeq ($(uname_S),AIX)
|
||||||
|
NO_STRCASESTR=YesPlease
|
||||||
|
NEEDS_LIBICONV=YesPlease
|
||||||
endif
|
endif
|
||||||
ifneq (,$(findstring arm,$(uname_M)))
|
ifneq (,$(findstring arm,$(uname_M)))
|
||||||
ARM_SHA1 = YesPlease
|
ARM_SHA1 = YesPlease
|
||||||
@ -219,31 +254,36 @@ endif
|
|||||||
|
|
||||||
-include config.mak
|
-include config.mak
|
||||||
|
|
||||||
|
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
|
||||||
|
SCRIPT_PERL += git-send-email.perl
|
||||||
|
endif
|
||||||
|
|
||||||
ifndef NO_CURL
|
ifndef NO_CURL
|
||||||
ifdef CURLDIR
|
ifdef CURLDIR
|
||||||
# This is still problematic -- gcc does not want -R.
|
# This is still problematic -- gcc does not always want -R.
|
||||||
ALL_CFLAGS += -I$(CURLDIR)/include
|
ALL_CFLAGS += -I$(CURLDIR)/include
|
||||||
CURL_LIBCURL = -L$(CURLDIR)/lib -R$(CURLDIR)/lib -lcurl
|
CURL_LIBCURL = -L$(CURLDIR)/lib -R$(CURLDIR)/lib -lcurl
|
||||||
else
|
else
|
||||||
CURL_LIBCURL = -lcurl
|
CURL_LIBCURL = -lcurl
|
||||||
endif
|
endif
|
||||||
PROGRAMS += git-http-fetch$X
|
PROGRAMS += git-http-fetch$X
|
||||||
ifndef NO_EXPAT
|
curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
|
||||||
EXPAT_LIBEXPAT = -lexpat
|
ifeq "$(curl_check)" "070908"
|
||||||
PROGRAMS += git-http-push$X
|
ifndef NO_EXPAT
|
||||||
|
EXPAT_LIBEXPAT = -lexpat
|
||||||
|
PROGRAMS += git-http-push$X
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
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
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef NO_OPENSSL
|
ifndef NO_OPENSSL
|
||||||
LIB_OBJS += epoch.o
|
LIB_OBJS += epoch.o
|
||||||
OPENSSL_LIBSSL = -lssl
|
OPENSSL_LIBSSL = -lssl
|
||||||
@ -285,12 +325,16 @@ ifdef NEEDS_NSL
|
|||||||
SIMPLE_LIB += -lnsl
|
SIMPLE_LIB += -lnsl
|
||||||
endif
|
endif
|
||||||
ifdef NO_STRCASESTR
|
ifdef NO_STRCASESTR
|
||||||
ALL_CFLAGS += -Dstrcasestr=gitstrcasestr -DNO_STRCASESTR=1
|
COMPAT_CFLAGS += -DNO_STRCASESTR
|
||||||
LIB_OBJS += compat/strcasestr.o
|
COMPAT_OBJS += compat/strcasestr.o
|
||||||
|
endif
|
||||||
|
ifdef NO_SETENV
|
||||||
|
COMPAT_CFLAGS += -DNO_SETENV
|
||||||
|
COMPAT_OBJS += compat/setenv.o
|
||||||
endif
|
endif
|
||||||
ifdef NO_MMAP
|
ifdef NO_MMAP
|
||||||
ALL_CFLAGS += -Dmmap=gitfakemmap -Dmunmap=gitfakemunmap -DNO_MMAP
|
COMPAT_CFLAGS += -DNO_MMAP
|
||||||
LIB_OBJS += compat/mmap.o
|
COMPAT_OBJS += compat/mmap.o
|
||||||
endif
|
endif
|
||||||
ifdef NO_IPV6
|
ifdef NO_IPV6
|
||||||
ALL_CFLAGS += -DNO_IPV6 -Dsockaddr_storage=sockaddr_in
|
ALL_CFLAGS += -DNO_IPV6 -Dsockaddr_storage=sockaddr_in
|
||||||
@ -314,31 +358,21 @@ endif
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ALL_CFLAGS += -DSHA1_HEADER=$(call shellquote,$(SHA1_HEADER))
|
ALL_CFLAGS += -DSHA1_HEADER=$(call shellquote,$(SHA1_HEADER)) $(COMPAT_CFLAGS)
|
||||||
|
LIB_OBJS += $(COMPAT_OBJS)
|
||||||
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
|
|
||||||
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
|
|
||||||
$(patsubst %.py,%,$(SCRIPT_PYTHON)) \
|
|
||||||
gitk git-cherry-pick
|
|
||||||
|
|
||||||
export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
|
export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
|
||||||
### Build rules
|
### Build rules
|
||||||
|
|
||||||
all: $(PROGRAMS) $(SCRIPTS)
|
all: $(ALL_PROGRAMS)
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(MAKE) -C templates
|
$(MAKE) -C templates
|
||||||
|
|
||||||
git: git.sh Makefile
|
git$X: git.c $(LIB_FILE) Makefile
|
||||||
rm -f $@+ $@
|
$(CC) -DGIT_EXEC_PATH='"$(bindir)"' -DGIT_VERSION='"$(GIT_VERSION)"' \
|
||||||
sed -e '1s|#!.*/sh|#!$(call shq,$(SHELL_PATH))|' \
|
$(CFLAGS) $(COMPAT_CFLAGS) -o $@ $(filter %.c,$^) $(LIB_FILE)
|
||||||
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
|
|
||||||
-e 's/@@X@@/$(X)/g' \
|
|
||||||
$(GIT_LIST_TWEAK) <$@.sh >$@+
|
|
||||||
chmod +x $@+
|
|
||||||
mv $@+ $@
|
|
||||||
|
|
||||||
$(filter-out git,$(patsubst %.sh,%,$(SCRIPT_SH))) : % : %.sh
|
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
|
||||||
rm -f $@
|
rm -f $@
|
||||||
sed -e '1s|#!.*/sh|#!$(call shq,$(SHELL_PATH))|' \
|
sed -e '1s|#!.*/sh|#!$(call shq,$(SHELL_PATH))|' \
|
||||||
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
|
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
|
||||||
@ -369,14 +403,16 @@ git-cherry-pick: git-revert
|
|||||||
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
|
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
|
||||||
|
|
||||||
git-%$X: %.o $(LIB_FILE)
|
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)
|
git-mailinfo$X : SIMPLE_LIB += $(LIB_4_ICONV)
|
||||||
$(SIMPLE_PROGRAMS) : $(LIB_FILE)
|
$(SIMPLE_PROGRAMS) : $(LIB_FILE)
|
||||||
$(SIMPLE_PROGRAMS) : git-%$X : %.o
|
$(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-local-fetch$X: fetch.o
|
||||||
git-ssh-fetch$X: rsh.o fetch.o
|
git-ssh-fetch$X: rsh.o fetch.o
|
||||||
git-ssh-upload$X: rsh.o
|
git-ssh-upload$X: rsh.o
|
||||||
@ -408,21 +444,21 @@ test: all
|
|||||||
$(MAKE) -C t/ all
|
$(MAKE) -C t/ all
|
||||||
|
|
||||||
test-date$X: test-date.c date.o ctype.o
|
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
|
test-delta$X: test-delta.c diff-delta.o patch-delta.o
|
||||||
$(CC) $(ALL_CFLAGS) -o $@ $^
|
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^
|
||||||
|
|
||||||
check:
|
check:
|
||||||
for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i; done
|
for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Installation rules
|
### Installation rules
|
||||||
|
|
||||||
install: $(PROGRAMS) $(SCRIPTS)
|
install: all
|
||||||
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(bindir))
|
$(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
|
$(MAKE) -C templates install
|
||||||
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
||||||
$(INSTALL) $(PYMODULES) $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
$(INSTALL) $(PYMODULES) $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
||||||
@ -435,20 +471,20 @@ install-doc:
|
|||||||
|
|
||||||
### Maintainer's dist rules
|
### 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' < $< > $@
|
sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@
|
||||||
|
|
||||||
GIT_TARNAME=git-core-$(GIT_VERSION)
|
GIT_TARNAME=git-$(GIT_VERSION)
|
||||||
dist: git-core.spec git-tar-tree
|
dist: git.spec git-tar-tree
|
||||||
./git-tar-tree HEAD $(GIT_TARNAME) > $(GIT_TARNAME).tar
|
./git-tar-tree HEAD $(GIT_TARNAME) > $(GIT_TARNAME).tar
|
||||||
@mkdir -p $(GIT_TARNAME)
|
@mkdir -p $(GIT_TARNAME)
|
||||||
@cp git-core.spec $(GIT_TARNAME)
|
@cp git.spec $(GIT_TARNAME)
|
||||||
$(TAR) rf $(GIT_TARNAME).tar $(GIT_TARNAME)/git-core.spec
|
$(TAR) rf $(GIT_TARNAME).tar $(GIT_TARNAME)/git.spec
|
||||||
@rm -rf $(GIT_TARNAME)
|
@rm -rf $(GIT_TARNAME)
|
||||||
gzip -f -9 $(GIT_TARNAME).tar
|
gzip -f -9 $(GIT_TARNAME).tar
|
||||||
|
|
||||||
rpm: dist
|
rpm: dist
|
||||||
$(RPMBUILD) -ta git-core-$(GIT_VERSION).tar.gz
|
$(RPMBUILD) -ta $(GIT_TARNAME).tar.gz
|
||||||
|
|
||||||
deb: dist
|
deb: dist
|
||||||
rm -rf $(GIT_TARNAME)
|
rm -rf $(GIT_TARNAME)
|
||||||
@ -459,9 +495,10 @@ deb: dist
|
|||||||
### Cleaning rules
|
### Cleaning rules
|
||||||
|
|
||||||
clean:
|
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 $(filter-out gitk,$(SCRIPTS))
|
||||||
rm -f git-core.spec *.pyc *.pyo
|
rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo
|
||||||
rm -rf $(GIT_TARNAME)
|
rm -rf $(GIT_TARNAME)
|
||||||
rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
|
rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
|
||||||
rm -f git-core_$(GIT_VERSION)-*.dsc
|
rm -f git-core_$(GIT_VERSION)-*.dsc
|
||||||
@ -469,3 +506,4 @@ clean:
|
|||||||
$(MAKE) -C Documentation/ clean
|
$(MAKE) -C Documentation/ clean
|
||||||
$(MAKE) -C templates clean
|
$(MAKE) -C templates clean
|
||||||
$(MAKE) -C t/ clean
|
$(MAKE) -C t/ clean
|
||||||
|
|
||||||
|
23
README
23
README
@ -35,7 +35,7 @@ the object (i.e. how it is used, and how it can refer to other
|
|||||||
objects). There are currently four different object types: "blob",
|
objects). There are currently four different object types: "blob",
|
||||||
"tree", "commit" and "tag".
|
"tree", "commit" and "tag".
|
||||||
|
|
||||||
A "blob" object cannot refer to any other object, and is, like the tag
|
A "blob" object cannot refer to any other object, and is, like the type
|
||||||
implies, a pure storage object containing some user data. It is used to
|
implies, a pure storage object containing some user data. It is used to
|
||||||
actually store the file data, i.e. a blob object is associated with some
|
actually store the file data, i.e. a blob object is associated with some
|
||||||
particular version of some file.
|
particular version of some file.
|
||||||
@ -64,7 +64,7 @@ symbolic name (of course!) and, optionally, a signature.
|
|||||||
|
|
||||||
Regardless of object type, all objects share the following
|
Regardless of object type, all objects share the following
|
||||||
characteristics: they are all deflated with zlib, and have a header
|
characteristics: they are all deflated with zlib, and have a header
|
||||||
that not only specifies their tag, but also provides size information
|
that not only specifies their type, but also provides size information
|
||||||
about the data in the object. It's worth noting that the SHA1 hash
|
about the data in the object. It's worth noting that the SHA1 hash
|
||||||
that is used to name the object is the hash of the original data
|
that is used to name the object is the hash of the original data
|
||||||
plus this header, so `sha1sum` 'file' does not match the object name
|
plus this header, so `sha1sum` 'file' does not match the object name
|
||||||
@ -76,7 +76,7 @@ As a result, the general consistency of an object can always be tested
|
|||||||
independently of the contents or the type of the object: all objects can
|
independently of the contents or the type of the object: all objects can
|
||||||
be validated by verifying that (a) their hashes match the content of the
|
be validated by verifying that (a) their hashes match the content of the
|
||||||
file and (b) the object successfully inflates to a stream of bytes that
|
file and (b) the object successfully inflates to a stream of bytes that
|
||||||
forms a sequence of <ascii tag without space> + <space> + <ascii decimal
|
forms a sequence of <ascii type without space> + <space> + <ascii decimal
|
||||||
size> + <byte\0> + <binary object data>.
|
size> + <byte\0> + <binary object data>.
|
||||||
|
|
||||||
The structured objects can further have their structure and
|
The structured objects can further have their structure and
|
||||||
@ -297,7 +297,7 @@ will not normally add totally new entries or remove old entries,
|
|||||||
i.e. it will normally just update existing cache entries.
|
i.e. it will normally just update existing cache entries.
|
||||||
|
|
||||||
To tell git that yes, you really do realize that certain files no
|
To tell git that yes, you really do realize that certain files no
|
||||||
longer exist in the archive, or that new files should be added, you
|
longer exist, or that new files should be added, you
|
||||||
should use the `--remove` and `--add` flags respectively.
|
should use the `--remove` and `--add` flags respectively.
|
||||||
|
|
||||||
NOTE! A `--remove` flag does 'not' mean that subsequent filenames will
|
NOTE! A `--remove` flag does 'not' mean that subsequent filenames will
|
||||||
@ -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,
|
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
|
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
|
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
|
result to the file pointed at by `.git/HEAD`, so that we can always see
|
||||||
last committed state was.
|
what the last committed state was.
|
||||||
|
|
||||||
Here is an ASCII art by Jon Loeliger that illustrates how
|
Here is an ASCII art by Jon Loeliger that illustrates how
|
||||||
various pieces fit together.
|
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`,
|
follow the convention of having the top commit name in `.git/HEAD`,
|
||||||
you can do
|
you can do
|
||||||
|
|
||||||
git-cat-file commit $(cat .git/HEAD)
|
git-cat-file commit HEAD
|
||||||
|
|
||||||
to see what the top commit was.
|
to see what the top commit was.
|
||||||
|
|
||||||
@ -515,8 +515,11 @@ index file, and you can just write the result out with
|
|||||||
Historical note. We did not have `-u` facility when this
|
Historical note. We did not have `-u` facility when this
|
||||||
section was first written, so we used to warn that
|
section was first written, so we used to warn that
|
||||||
the merge is done in the index file, not in your
|
the merge is done in the index file, not in your
|
||||||
working directory, and your working directory will no longer match your
|
working tree, and your working tree will not match your
|
||||||
index.
|
index after this step.
|
||||||
|
This is no longer true. The above command, thanks to `-u`
|
||||||
|
option, updates your working tree with the merge results for
|
||||||
|
paths that have been trivially merged.
|
||||||
|
|
||||||
|
|
||||||
8) Merging multiple trees, continued
|
8) Merging multiple trees, continued
|
||||||
@ -579,7 +582,7 @@ The above is the description of a git merge at the lowest level,
|
|||||||
to help you understand what conceptually happens under the hood.
|
to help you understand what conceptually happens under the hood.
|
||||||
In practice, nobody, not even git itself, uses three `git-cat-file`
|
In practice, nobody, not even git itself, uses three `git-cat-file`
|
||||||
for this. There is `git-merge-index` program that extracts the
|
for this. There is `git-merge-index` program that extracts the
|
||||||
stages to temporary files and calls a `merge` script on it
|
stages to temporary files and calls a "merge" script on it:
|
||||||
|
|
||||||
git-merge-index git-merge-one-file hello.c
|
git-merge-index git-merge-one-file hello.c
|
||||||
|
|
||||||
|
158
apply.c
158
apply.c
@ -16,6 +16,10 @@
|
|||||||
// --numstat does numeric diffstat, and doesn't actually apply
|
// --numstat does numeric diffstat, and doesn't actually apply
|
||||||
// --index-info shows the old and new index info for paths if available.
|
// --index-info shows the old and new index info for paths if available.
|
||||||
//
|
//
|
||||||
|
static const char *prefix;
|
||||||
|
static int prefix_length = -1;
|
||||||
|
|
||||||
|
static int allow_binary_replacement = 0;
|
||||||
static int check_index = 0;
|
static int check_index = 0;
|
||||||
static int write_index = 0;
|
static int write_index = 0;
|
||||||
static int diffstat = 0;
|
static int diffstat = 0;
|
||||||
@ -27,7 +31,7 @@ static int no_add = 0;
|
|||||||
static int show_index_info = 0;
|
static int show_index_info = 0;
|
||||||
static int line_termination = '\n';
|
static int line_termination = '\n';
|
||||||
static const char apply_usage[] =
|
static const char apply_usage[] =
|
||||||
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--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
|
* For "diff-stat" like behaviour, we keep track of the biggest change
|
||||||
@ -80,14 +84,11 @@ static void *read_patch_file(int fd, unsigned long *sizep)
|
|||||||
buffer = xrealloc(buffer, alloc);
|
buffer = xrealloc(buffer, alloc);
|
||||||
nr = alloc - size;
|
nr = alloc - size;
|
||||||
}
|
}
|
||||||
nr = read(fd, buffer + size, nr);
|
nr = xread(fd, buffer + size, nr);
|
||||||
if (!nr)
|
if (!nr)
|
||||||
break;
|
break;
|
||||||
if (nr < 0) {
|
if (nr < 0)
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
die("git-apply: read returned %s", strerror(errno));
|
die("git-apply: read returned %s", strerror(errno));
|
||||||
}
|
|
||||||
size += nr;
|
size += nr;
|
||||||
}
|
}
|
||||||
*sizep = size;
|
*sizep = size;
|
||||||
@ -370,7 +371,7 @@ static int gitdiff_index(const char *line, struct patch *patch)
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
ptr = strchr(line, '.');
|
ptr = strchr(line, '.');
|
||||||
if (!ptr || ptr[1] != '.' || 40 <= ptr - line)
|
if (!ptr || ptr[1] != '.' || 40 < ptr - line)
|
||||||
return 0;
|
return 0;
|
||||||
len = ptr - line;
|
len = ptr - line;
|
||||||
memcpy(patch->old_sha1_prefix, line, len);
|
memcpy(patch->old_sha1_prefix, line, len);
|
||||||
@ -384,7 +385,7 @@ static int gitdiff_index(const char *line, struct patch *patch)
|
|||||||
ptr = eol;
|
ptr = eol;
|
||||||
len = ptr - line;
|
len = ptr - line;
|
||||||
|
|
||||||
if (40 <= len)
|
if (40 < len)
|
||||||
return 0;
|
return 0;
|
||||||
memcpy(patch->new_sha1_prefix, line, len);
|
memcpy(patch->new_sha1_prefix, line, len);
|
||||||
patch->new_sha1_prefix[len] = 0;
|
patch->new_sha1_prefix[len] = 0;
|
||||||
@ -891,16 +892,34 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
|
|||||||
|
|
||||||
patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch);
|
patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch);
|
||||||
|
|
||||||
if (!patchsize && !metadata_changes(patch)) {
|
if (!patchsize) {
|
||||||
static const char binhdr[] = "Binary files ";
|
static const char *binhdr[] = {
|
||||||
|
"Binary files ",
|
||||||
|
"Files ",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
int hd = hdrsize + offset;
|
||||||
|
unsigned long llen = linelen(buffer + hd, size - hd);
|
||||||
|
|
||||||
if (sizeof(binhdr) - 1 < size - offset - hdrsize &&
|
if (!memcmp(" differ\n", buffer + hd + llen - 8, 8))
|
||||||
!memcmp(binhdr, buffer + hdrsize, sizeof(binhdr)-1))
|
for (i = 0; binhdr[i]; i++) {
|
||||||
patch->is_binary = 1;
|
int len = strlen(binhdr[i]);
|
||||||
|
if (len < size - hd &&
|
||||||
|
!memcmp(binhdr[i], buffer + hd, len)) {
|
||||||
|
patch->is_binary = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (patch->is_binary && !apply && !check)
|
/* Empty patch cannot be applied if:
|
||||||
;
|
* - it is a binary patch and we do not do binary_replace, or
|
||||||
else
|
* - 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);
|
die("patch with only garbage at line %d", linenr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -984,13 +1003,8 @@ static int read_old_data(struct stat *st, const char *path, void *buf, unsigned
|
|||||||
return error("unable to open %s", path);
|
return error("unable to open %s", path);
|
||||||
got = 0;
|
got = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret = read(fd, buf + got, size - got);
|
int ret = xread(fd, buf + got, size - got);
|
||||||
if (ret < 0) {
|
if (ret <= 0)
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!ret)
|
|
||||||
break;
|
break;
|
||||||
got += ret;
|
got += ret;
|
||||||
}
|
}
|
||||||
@ -1154,10 +1168,77 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
|
|||||||
static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
|
static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
|
||||||
{
|
{
|
||||||
struct fragment *frag = patch->fragments;
|
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) {
|
while (frag) {
|
||||||
if (apply_one_fragment(desc, frag) < 0)
|
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;
|
frag = frag->next;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1199,6 +1280,7 @@ static int check_patch(struct patch *patch)
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
const char *old_name = patch->old_name;
|
const char *old_name = patch->old_name;
|
||||||
const char *new_name = patch->new_name;
|
const char *new_name = patch->new_name;
|
||||||
|
const char *name = old_name ? old_name : new_name;
|
||||||
|
|
||||||
if (old_name) {
|
if (old_name) {
|
||||||
int changed;
|
int changed;
|
||||||
@ -1273,7 +1355,7 @@ static int check_patch(struct patch *patch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (apply_data(patch, &st) < 0)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1510,12 +1592,9 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
while (size) {
|
while (size) {
|
||||||
int written = write(fd, buf, size);
|
int written = xwrite(fd, buf, size);
|
||||||
if (written < 0) {
|
if (written < 0)
|
||||||
if (errno == EINTR || errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
die("writing file %s: %s", path, strerror(errno));
|
die("writing file %s: %s", path, strerror(errno));
|
||||||
}
|
|
||||||
if (!written)
|
if (!written)
|
||||||
die("out of space writing file %s", path);
|
die("out of space writing file %s", path);
|
||||||
buf += written;
|
buf += written;
|
||||||
@ -1619,6 +1698,12 @@ static int use_patch(struct patch *p)
|
|||||||
return 0;
|
return 0;
|
||||||
x = x->next;
|
x = x->next;
|
||||||
}
|
}
|
||||||
|
if (0 < prefix_length) {
|
||||||
|
int pathlen = strlen(pathname);
|
||||||
|
if (pathlen <= prefix_length ||
|
||||||
|
memcmp(prefix, pathname, prefix_length))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1722,6 +1807,10 @@ int main(int argc, char **argv)
|
|||||||
diffstat = 1;
|
diffstat = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(arg, "--allow-binary-replacement")) {
|
||||||
|
allow_binary_replacement = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "--numstat")) {
|
if (!strcmp(arg, "--numstat")) {
|
||||||
apply = 0;
|
apply = 0;
|
||||||
numstat = 1;
|
numstat = 1;
|
||||||
@ -1754,6 +1843,15 @@ int main(int argc, char **argv)
|
|||||||
line_termination = 0;
|
line_termination = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_index && prefix_length < 0) {
|
||||||
|
prefix = setup_git_directory();
|
||||||
|
prefix_length = prefix ? strlen(prefix) : 0;
|
||||||
|
git_config(git_default_config);
|
||||||
|
}
|
||||||
|
if (0 < prefix_length)
|
||||||
|
arg = prefix_filename(prefix, prefix_length, arg);
|
||||||
|
|
||||||
fd = open(arg, O_RDONLY);
|
fd = open(arg, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
usage(apply_usage);
|
usage(apply_usage);
|
||||||
|
122
cache.h
122
cache.h
@ -1,23 +1,7 @@
|
|||||||
#ifndef CACHE_H
|
#ifndef CACHE_H
|
||||||
#define CACHE_H
|
#define CACHE_H
|
||||||
|
|
||||||
#include <unistd.h>
|
#include "git-compat-util.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#ifndef NO_MMAP
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
#include SHA1_HEADER
|
#include SHA1_HEADER
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
@ -36,15 +20,6 @@
|
|||||||
#define DTYPE(de) DT_UNKNOWN
|
#define DTYPE(de) DT_UNKNOWN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define NORETURN __attribute__((__noreturn__))
|
|
||||||
#else
|
|
||||||
#define NORETURN
|
|
||||||
#ifndef __attribute__
|
|
||||||
#define __attribute__(x)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Intensive research over the course of many years has shown that
|
* Intensive research over the course of many years has shown that
|
||||||
* port 9418 is totally unused by anything else. Or
|
* port 9418 is totally unused by anything else. Or
|
||||||
@ -147,8 +122,10 @@ extern char *get_graft_file(void);
|
|||||||
#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
|
#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
|
||||||
|
|
||||||
extern const char **get_pathspec(const char *prefix, const char **pathspec);
|
extern const char **get_pathspec(const char *prefix, const char **pathspec);
|
||||||
|
extern const char *setup_git_directory_gently(int *);
|
||||||
extern const char *setup_git_directory(void);
|
extern const char *setup_git_directory(void);
|
||||||
extern const char *prefix_path(const char *prefix, int len, const char *path);
|
extern const char *prefix_path(const char *prefix, int len, const char *path);
|
||||||
|
extern const char *prefix_filename(const char *prefix, int len, const char *path);
|
||||||
|
|
||||||
#define alloc_nr(x) (((x)+16)*3/2)
|
#define alloc_nr(x) (((x)+16)*3/2)
|
||||||
|
|
||||||
@ -167,6 +144,7 @@ extern int ce_match_stat(struct cache_entry *ce, struct stat *st);
|
|||||||
extern int ce_modified(struct cache_entry *ce, struct stat *st);
|
extern int ce_modified(struct cache_entry *ce, struct stat *st);
|
||||||
extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
|
extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
|
||||||
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type);
|
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type);
|
||||||
|
extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
|
||||||
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
|
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
|
||||||
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
|
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
|
||||||
|
|
||||||
@ -179,6 +157,12 @@ extern int commit_index_file(struct cache_file *);
|
|||||||
extern void rollback_index_file(struct cache_file *);
|
extern void rollback_index_file(struct cache_file *);
|
||||||
|
|
||||||
extern int trust_executable_bit;
|
extern int trust_executable_bit;
|
||||||
|
extern int only_use_symrefs;
|
||||||
|
extern int diff_rename_limit_default;
|
||||||
|
|
||||||
|
#define GIT_REPO_VERSION 0
|
||||||
|
extern int repository_format_version;
|
||||||
|
extern int check_repository_format(void);
|
||||||
|
|
||||||
#define MTIME_CHANGED 0x0001
|
#define MTIME_CHANGED 0x0001
|
||||||
#define CTIME_CHANGED 0x0002
|
#define CTIME_CHANGED 0x0002
|
||||||
@ -201,6 +185,7 @@ int git_mkstemp(char *path, size_t n, const char *template);
|
|||||||
|
|
||||||
int safe_create_leading_directories(char *path);
|
int safe_create_leading_directories(char *path);
|
||||||
char *safe_strncpy(char *, const char *, size_t);
|
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 */
|
/* 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);
|
extern int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void *buffer, unsigned long size);
|
||||||
@ -241,11 +226,6 @@ extern const char *resolve_ref(const char *path, unsigned char *sha1, int);
|
|||||||
extern int create_symref(const char *git_HEAD, const char *refs_heads_master);
|
extern int create_symref(const char *git_HEAD, const char *refs_heads_master);
|
||||||
extern int validate_symref(const char *git_HEAD);
|
extern int validate_symref(const char *git_HEAD);
|
||||||
|
|
||||||
/* General helper functions */
|
|
||||||
extern void usage(const char *err) NORETURN;
|
|
||||||
extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
|
|
||||||
extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
|
|
||||||
|
|
||||||
extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);
|
extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2);
|
||||||
extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2);
|
extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2);
|
||||||
|
|
||||||
@ -257,35 +237,11 @@ extern void *read_object_with_reference(const unsigned char *sha1,
|
|||||||
const char *show_date(unsigned long time, int timezone);
|
const char *show_date(unsigned long time, int timezone);
|
||||||
int parse_date(const char *date, char *buf, int bufsize);
|
int parse_date(const char *date, char *buf, int bufsize);
|
||||||
void datestamp(char *buf, int bufsize);
|
void datestamp(char *buf, int bufsize);
|
||||||
|
unsigned long approxidate(const char *);
|
||||||
|
|
||||||
extern int setup_ident(void);
|
extern int setup_ident(void);
|
||||||
extern char *get_ident(const char *name, const char *email, const char *date_str);
|
extern const char *git_author_info(void);
|
||||||
extern char *git_author_info(void);
|
extern const char *git_committer_info(void);
|
||||||
extern char *git_committer_info(void);
|
|
||||||
|
|
||||||
static inline void *xmalloc(size_t size)
|
|
||||||
{
|
|
||||||
void *ret = malloc(size);
|
|
||||||
if (!ret)
|
|
||||||
die("Out of memory, malloc failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void *xrealloc(void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
void *ret = realloc(ptr, size);
|
|
||||||
if (!ret)
|
|
||||||
die("Out of memory, realloc failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void *xcalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *ret = calloc(nmemb, size);
|
|
||||||
if (!ret)
|
|
||||||
die("Out of memory, calloc failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct checkout {
|
struct checkout {
|
||||||
const char *base_dir;
|
const char *base_dir;
|
||||||
@ -364,55 +320,27 @@ extern void packed_object_info_detail(struct pack_entry *, char *, unsigned long
|
|||||||
/* Dumb servers support */
|
/* Dumb servers support */
|
||||||
extern int update_server_info(int);
|
extern int update_server_info(int);
|
||||||
|
|
||||||
#ifdef NO_MMAP
|
|
||||||
|
|
||||||
#ifndef PROT_READ
|
|
||||||
#define PROT_READ 1
|
|
||||||
#define PROT_WRITE 2
|
|
||||||
#define MAP_PRIVATE 1
|
|
||||||
#define MAP_FAILED ((void*)-1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);
|
|
||||||
extern int gitfakemunmap(void *start, size_t length);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef int (*config_fn_t)(const char *, const char *);
|
typedef int (*config_fn_t)(const char *, const char *);
|
||||||
extern int git_default_config(const char *, const char *);
|
extern int git_default_config(const char *, const char *);
|
||||||
|
extern int git_config_from_file(config_fn_t fn, const char *);
|
||||||
extern int git_config(config_fn_t fn);
|
extern int git_config(config_fn_t fn);
|
||||||
extern int git_config_int(const char *, const char *);
|
extern int git_config_int(const char *, const char *);
|
||||||
extern int git_config_bool(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);
|
||||||
|
extern int check_repository_format_version(const char *var, const char *value);
|
||||||
|
|
||||||
#define MAX_GITNAME (1000)
|
#define MAX_GITNAME (1000)
|
||||||
extern char git_default_email[MAX_GITNAME];
|
extern char git_default_email[MAX_GITNAME];
|
||||||
extern char git_default_name[MAX_GITNAME];
|
extern char git_default_name[MAX_GITNAME];
|
||||||
|
|
||||||
/* Sane ctype - no locale, and works with signed chars */
|
#define MAX_ENCODING_LENGTH 64
|
||||||
#undef isspace
|
extern char git_commit_encoding[MAX_ENCODING_LENGTH];
|
||||||
#undef isdigit
|
|
||||||
#undef isalpha
|
|
||||||
#undef isalnum
|
|
||||||
#undef tolower
|
|
||||||
#undef toupper
|
|
||||||
extern unsigned char sane_ctype[256];
|
|
||||||
#define GIT_SPACE 0x01
|
|
||||||
#define GIT_DIGIT 0x02
|
|
||||||
#define GIT_ALPHA 0x04
|
|
||||||
#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
|
|
||||||
#define isspace(x) sane_istest(x,GIT_SPACE)
|
|
||||||
#define isdigit(x) sane_istest(x,GIT_DIGIT)
|
|
||||||
#define isalpha(x) sane_istest(x,GIT_ALPHA)
|
|
||||||
#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
|
|
||||||
#define tolower(x) sane_case((unsigned char)(x), 0x20)
|
|
||||||
#define toupper(x) sane_case((unsigned char)(x), 0)
|
|
||||||
|
|
||||||
static inline int sane_case(int x, int high)
|
|
||||||
{
|
|
||||||
if (sane_istest(x, GIT_ALPHA))
|
|
||||||
x = (x & ~0x20) | high;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int copy_fd(int ifd, int ofd);
|
extern int copy_fd(int ifd, int ofd);
|
||||||
|
|
||||||
|
/* Finish off pack transfer receiving end */
|
||||||
|
extern int receive_unpack_pack(int fd[2], const char *me, int quiet);
|
||||||
|
extern int receive_keep_pack(int fd[2], const char *me);
|
||||||
|
|
||||||
#endif /* CACHE_H */
|
#endif /* CACHE_H */
|
||||||
|
49
cat-file.c
49
cat-file.c
@ -11,37 +11,52 @@ int main(int argc, char **argv)
|
|||||||
char type[20];
|
char type[20];
|
||||||
void *buf;
|
void *buf;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
int opt;
|
||||||
|
|
||||||
setup_git_directory();
|
setup_git_directory();
|
||||||
if (argc != 3 || get_sha1(argv[2], sha1))
|
if (argc != 3 || get_sha1(argv[2], sha1))
|
||||||
usage("git-cat-file [-t | -s | <type>] <sha1>");
|
usage("git-cat-file [-t|-s|-e|<type>] <sha1>");
|
||||||
|
|
||||||
if (!strcmp("-t", argv[1]) || !strcmp("-s", argv[1])) {
|
opt = 0;
|
||||||
if (!sha1_object_info(sha1, type,
|
if ( argv[1][0] == '-' ) {
|
||||||
argv[1][1] == 's' ? &size : NULL)) {
|
opt = argv[1][1];
|
||||||
switch (argv[1][1]) {
|
if ( !opt || argv[1][2] )
|
||||||
case 't':
|
opt = -1; /* Not a single character option */
|
||||||
printf("%s\n", type);
|
}
|
||||||
break;
|
|
||||||
case 's':
|
buf = NULL;
|
||||||
printf("%lu\n", size);
|
switch (opt) {
|
||||||
break;
|
case 't':
|
||||||
}
|
if (!sha1_object_info(sha1, type, NULL)) {
|
||||||
|
printf("%s\n", type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
buf = NULL;
|
break;
|
||||||
} else {
|
|
||||||
|
case 's':
|
||||||
|
if (!sha1_object_info(sha1, type, &size)) {
|
||||||
|
printf("%lu\n", size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
return !has_sha1_file(sha1);
|
||||||
|
|
||||||
|
case 0:
|
||||||
buf = read_object_with_reference(sha1, argv[1], &size, NULL);
|
buf = read_object_with_reference(sha1, argv[1], &size, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
die("git-cat-file: unknown option: %s\n", argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buf)
|
if (!buf)
|
||||||
die("git-cat-file %s: bad file", argv[2]);
|
die("git-cat-file %s: bad file", argv[2]);
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
long ret = write(1, buf, size);
|
long ret = xwrite(1, buf, size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
/* Ignore epipe */
|
/* Ignore epipe */
|
||||||
if (errno == EPIPE)
|
if (errno == EPIPE)
|
||||||
break;
|
break;
|
||||||
|
@ -34,6 +34,10 @@
|
|||||||
*/
|
*/
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
|
static const char *prefix;
|
||||||
|
static int prefix_length;
|
||||||
|
static int checkout_stage; /* default to checkout stage0 */
|
||||||
|
|
||||||
static struct checkout state = {
|
static struct checkout state = {
|
||||||
.base_dir = "",
|
.base_dir = "",
|
||||||
.base_dir_len = 0,
|
.base_dir_len = 0,
|
||||||
@ -45,20 +49,36 @@ static struct checkout state = {
|
|||||||
|
|
||||||
static int checkout_file(const char *name)
|
static int checkout_file(const char *name)
|
||||||
{
|
{
|
||||||
int pos = cache_name_pos(name, strlen(name));
|
int namelen = strlen(name);
|
||||||
if (pos < 0) {
|
int pos = cache_name_pos(name, namelen);
|
||||||
if (!state.quiet) {
|
int has_same_name = 0;
|
||||||
pos = -pos - 1;
|
|
||||||
fprintf(stderr,
|
if (pos < 0)
|
||||||
"git-checkout-index: %s is %s.\n",
|
pos = -pos - 1;
|
||||||
name,
|
|
||||||
(pos < active_nr &&
|
while (pos < active_nr) {
|
||||||
!strcmp(active_cache[pos]->name, name)) ?
|
struct cache_entry *ce = active_cache[pos];
|
||||||
"unmerged" : "not in the cache");
|
if (ce_namelen(ce) != namelen ||
|
||||||
}
|
memcmp(ce->name, name, namelen))
|
||||||
return -1;
|
break;
|
||||||
|
has_same_name = 1;
|
||||||
|
if (checkout_stage == ce_stage(ce))
|
||||||
|
return checkout_entry(ce, &state);
|
||||||
|
pos++;
|
||||||
}
|
}
|
||||||
return checkout_entry(active_cache[pos], &state);
|
|
||||||
|
if (!state.quiet) {
|
||||||
|
fprintf(stderr, "git-checkout-index: %s ", name);
|
||||||
|
if (!has_same_name)
|
||||||
|
fprintf(stderr, "is not in the cache");
|
||||||
|
else if (checkout_stage)
|
||||||
|
fprintf(stderr, "does not exist at stage %d",
|
||||||
|
checkout_stage);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "is unmerged");
|
||||||
|
fputc('\n', stderr);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int checkout_all(void)
|
static int checkout_all(void)
|
||||||
@ -67,7 +87,11 @@ static int checkout_all(void)
|
|||||||
|
|
||||||
for (i = 0; i < active_nr ; i++) {
|
for (i = 0; i < active_nr ; i++) {
|
||||||
struct cache_entry *ce = active_cache[i];
|
struct cache_entry *ce = active_cache[i];
|
||||||
if (ce_stage(ce))
|
if (ce_stage(ce) != checkout_stage)
|
||||||
|
continue;
|
||||||
|
if (prefix && *prefix &&
|
||||||
|
(ce_namelen(ce) <= prefix_length ||
|
||||||
|
memcmp(prefix, ce->name, prefix_length)))
|
||||||
continue;
|
continue;
|
||||||
if (checkout_entry(ce, &state) < 0)
|
if (checkout_entry(ce, &state) < 0)
|
||||||
errs++;
|
errs++;
|
||||||
@ -81,7 +105,7 @@ static int checkout_all(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char checkout_cache_usage[] =
|
static const char checkout_cache_usage[] =
|
||||||
"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--prefix=<string>] [--] <file>...";
|
"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]] [--prefix=<string>] [--] <file>...";
|
||||||
|
|
||||||
static struct cache_file cache_file;
|
static struct cache_file cache_file;
|
||||||
|
|
||||||
@ -91,6 +115,9 @@ int main(int argc, char **argv)
|
|||||||
int newfd = -1;
|
int newfd = -1;
|
||||||
int all = 0;
|
int all = 0;
|
||||||
|
|
||||||
|
prefix = setup_git_directory();
|
||||||
|
prefix_length = prefix ? strlen(prefix) : 0;
|
||||||
|
|
||||||
if (read_cache() < 0) {
|
if (read_cache() < 0) {
|
||||||
die("invalid cache");
|
die("invalid cache");
|
||||||
}
|
}
|
||||||
@ -128,11 +155,19 @@ int main(int argc, char **argv)
|
|||||||
die("cannot open index.lock file.");
|
die("cannot open index.lock file.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!memcmp(arg, "--prefix=", 9)) {
|
if (!strncmp(arg, "--prefix=", 9)) {
|
||||||
state.base_dir = arg+9;
|
state.base_dir = arg+9;
|
||||||
state.base_dir_len = strlen(state.base_dir);
|
state.base_dir_len = strlen(state.base_dir);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strncmp(arg, "--stage=", 8)) {
|
||||||
|
int ch = arg[8];
|
||||||
|
if ('1' <= ch && ch <= '3')
|
||||||
|
checkout_stage = arg[8] - '0';
|
||||||
|
else
|
||||||
|
die("stage should be between 1 and 3");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (arg[0] == '-')
|
if (arg[0] == '-')
|
||||||
usage(checkout_cache_usage);
|
usage(checkout_cache_usage);
|
||||||
break;
|
break;
|
||||||
@ -155,7 +190,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (all)
|
if (all)
|
||||||
die("git-checkout-index: don't mix '--all' and explicit filenames");
|
die("git-checkout-index: don't mix '--all' and explicit filenames");
|
||||||
checkout_file(arg);
|
checkout_file(prefix_path(prefix, prefix_length, arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all)
|
if (all)
|
||||||
|
153
clone-pack.c
153
clone-pack.c
@ -1,7 +1,6 @@
|
|||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
#include "pkt-line.h"
|
#include "pkt-line.h"
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
static const char clone_pack_usage[] =
|
static const char clone_pack_usage[] =
|
||||||
"git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
|
"git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
|
||||||
@ -112,139 +111,6 @@ static void write_refs(struct ref *ref)
|
|||||||
free(head_path);
|
free(head_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int finish_pack(const char *pack_tmp_name)
|
|
||||||
{
|
|
||||||
int pipe_fd[2];
|
|
||||||
pid_t pid;
|
|
||||||
char idx[PATH_MAX];
|
|
||||||
char final[PATH_MAX];
|
|
||||||
char hash[41];
|
|
||||||
unsigned char sha1[20];
|
|
||||||
char *cp;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (pipe(pipe_fd) < 0)
|
|
||||||
die("git-clone-pack: unable to set up pipe");
|
|
||||||
|
|
||||||
strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */
|
|
||||||
cp = strrchr(idx, '/');
|
|
||||||
memcpy(cp, "/pidx", 5);
|
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid < 0)
|
|
||||||
die("git-clone-pack: unable to fork off git-index-pack");
|
|
||||||
if (!pid) {
|
|
||||||
close(0);
|
|
||||||
dup2(pipe_fd[1], 1);
|
|
||||||
close(pipe_fd[0]);
|
|
||||||
close(pipe_fd[1]);
|
|
||||||
execlp("git-index-pack","git-index-pack",
|
|
||||||
"-o", idx, pack_tmp_name, NULL);
|
|
||||||
error("cannot exec git-index-pack <%s> <%s>",
|
|
||||||
idx, pack_tmp_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
close(pipe_fd[1]);
|
|
||||||
if (read(pipe_fd[0], hash, 40) != 40) {
|
|
||||||
error("git-clone-pack: unable to read from git-index-pack");
|
|
||||||
err = 1;
|
|
||||||
}
|
|
||||||
close(pipe_fd[0]);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
int status, code;
|
|
||||||
int retval = waitpid(pid, &status, 0);
|
|
||||||
|
|
||||||
if (retval < 0) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
error("waitpid failed (%s)", strerror(retval));
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
if (WIFSIGNALED(status)) {
|
|
||||||
int sig = WTERMSIG(status);
|
|
||||||
error("git-index-pack died of signal %d", sig);
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
if (!WIFEXITED(status)) {
|
|
||||||
error("git-index-pack died of unnatural causes %d",
|
|
||||||
status);
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
code = WEXITSTATUS(status);
|
|
||||||
if (code) {
|
|
||||||
error("git-index-pack died with error code %d", code);
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
if (err)
|
|
||||||
goto error_die;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
hash[40] = 0;
|
|
||||||
if (get_sha1_hex(hash, sha1)) {
|
|
||||||
error("git-index-pack reported nonsense '%s'", hash);
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
/* Now we have pack in pack_tmp_name[], and
|
|
||||||
* idx in idx[]; rename them to their final names.
|
|
||||||
*/
|
|
||||||
snprintf(final, sizeof(final),
|
|
||||||
"%s/pack/pack-%s.pack", get_object_directory(), hash);
|
|
||||||
move_temp_to_file(pack_tmp_name, final);
|
|
||||||
chmod(final, 0444);
|
|
||||||
snprintf(final, sizeof(final),
|
|
||||||
"%s/pack/pack-%s.idx", get_object_directory(), hash);
|
|
||||||
move_temp_to_file(idx, final);
|
|
||||||
chmod(final, 0444);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error_die:
|
|
||||||
unlink(idx);
|
|
||||||
unlink(pack_tmp_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int clone_without_unpack(int fd[2])
|
|
||||||
{
|
|
||||||
char tmpfile[PATH_MAX];
|
|
||||||
int ofd, ifd;
|
|
||||||
|
|
||||||
ifd = fd[0];
|
|
||||||
snprintf(tmpfile, sizeof(tmpfile),
|
|
||||||
"%s/pack/tmp-XXXXXX", get_object_directory());
|
|
||||||
ofd = mkstemp(tmpfile);
|
|
||||||
if (ofd < 0)
|
|
||||||
return error("unable to create temporary file %s", tmpfile);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
char buf[8192];
|
|
||||||
ssize_t sz, wsz, pos;
|
|
||||||
sz = read(ifd, buf, sizeof(buf));
|
|
||||||
if (sz == 0)
|
|
||||||
break;
|
|
||||||
if (sz < 0) {
|
|
||||||
error("error reading pack (%s)", strerror(errno));
|
|
||||||
close(ofd);
|
|
||||||
unlink(tmpfile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pos = 0;
|
|
||||||
while (pos < sz) {
|
|
||||||
wsz = write(ofd, buf + pos, sz - pos);
|
|
||||||
if (wsz < 0) {
|
|
||||||
error("error writing pack (%s)",
|
|
||||||
strerror(errno));
|
|
||||||
close(ofd);
|
|
||||||
unlink(tmpfile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pos += wsz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(ofd);
|
|
||||||
return finish_pack(tmpfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int clone_pack(int fd[2], int nr_match, char **match)
|
static int clone_pack(int fd[2], int nr_match, char **match)
|
||||||
{
|
{
|
||||||
struct ref *refs;
|
struct ref *refs;
|
||||||
@ -257,10 +123,19 @@ static int clone_pack(int fd[2], int nr_match, char **match)
|
|||||||
}
|
}
|
||||||
clone_handshake(fd, refs);
|
clone_handshake(fd, refs);
|
||||||
|
|
||||||
status = clone_without_unpack(fd);
|
status = receive_keep_pack(fd, "git-clone-pack");
|
||||||
|
|
||||||
if (!status)
|
if (!status) {
|
||||||
write_refs(refs);
|
if (nr_match == 0)
|
||||||
|
write_refs(refs);
|
||||||
|
else
|
||||||
|
while (refs) {
|
||||||
|
printf("%s %s\n",
|
||||||
|
sha1_to_hex(refs->old_sha1),
|
||||||
|
refs->name);
|
||||||
|
refs = refs->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,6 +146,8 @@ int main(int argc, char **argv)
|
|||||||
int fd[2];
|
int fd[2];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
|
setup_git_directory();
|
||||||
|
|
||||||
nr_heads = 0;
|
nr_heads = 0;
|
||||||
heads = NULL;
|
heads = NULL;
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
@ -283,8 +160,6 @@ int main(int argc, char **argv)
|
|||||||
exec = arg + 7;
|
exec = arg + 7;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp("--keep", arg))
|
|
||||||
continue;
|
|
||||||
usage(clone_pack_usage);
|
usage(clone_pack_usage);
|
||||||
}
|
}
|
||||||
dest = arg;
|
dest = arg;
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# If you installed git by hand previously, you may find this
|
|
||||||
# script useful to remove the symbolic links that we shipped
|
|
||||||
# for backward compatibility.
|
|
||||||
#
|
|
||||||
# Running this script with the previous installation directory
|
|
||||||
# like this:
|
|
||||||
#
|
|
||||||
# $ cmd-rename.sh /usr/local/bin/
|
|
||||||
#
|
|
||||||
# would clean them.
|
|
||||||
|
|
||||||
d="$1"
|
|
||||||
test -d "$d" || exit
|
|
||||||
while read old new
|
|
||||||
do
|
|
||||||
rm -f "$d/$old"
|
|
||||||
done <<\EOF
|
|
||||||
git-add-script git-add
|
|
||||||
git-archimport-script git-archimport
|
|
||||||
git-bisect-script git-bisect
|
|
||||||
git-branch-script git-branch
|
|
||||||
git-checkout-script git-checkout
|
|
||||||
git-cherry-pick-script git-cherry-pick
|
|
||||||
git-clone-script git-clone
|
|
||||||
git-commit-script git-commit
|
|
||||||
git-count-objects-script git-count-objects
|
|
||||||
git-cvsimport-script git-cvsimport
|
|
||||||
git-diff-script git-diff
|
|
||||||
git-send-email-script git-send-email
|
|
||||||
git-fetch-script git-fetch
|
|
||||||
git-format-patch-script git-format-patch
|
|
||||||
git-log-script git-log
|
|
||||||
git-ls-remote-script git-ls-remote
|
|
||||||
git-merge-one-file-script git-merge-one-file
|
|
||||||
git-octopus-script git-octopus
|
|
||||||
git-parse-remote-script git-parse-remote
|
|
||||||
git-prune-script git-prune
|
|
||||||
git-pull-script git-pull
|
|
||||||
git-push-script git-push
|
|
||||||
git-rebase-script git-rebase
|
|
||||||
git-relink-script git-relink
|
|
||||||
git-rename-script git-rename
|
|
||||||
git-repack-script git-repack
|
|
||||||
git-request-pull-script git-request-pull
|
|
||||||
git-reset-script git-reset
|
|
||||||
git-resolve-script git-resolve
|
|
||||||
git-revert-script git-revert
|
|
||||||
git-sh-setup-script git-sh-setup
|
|
||||||
git-status-script git-status
|
|
||||||
git-tag-script git-tag
|
|
||||||
git-verify-tag-script git-verify-tag
|
|
||||||
git-http-pull git-http-fetch
|
|
||||||
git-local-pull git-local-fetch
|
|
||||||
git-checkout-cache git-checkout-index
|
|
||||||
git-diff-cache git-diff-index
|
|
||||||
git-merge-cache git-merge-index
|
|
||||||
git-update-cache git-update-index
|
|
||||||
git-convert-cache git-convert-objects
|
|
||||||
git-fsck-cache git-fsck-objects
|
|
||||||
EOF
|
|
@ -91,6 +91,8 @@ int main(int argc, char **argv)
|
|||||||
if (argc < 2 || get_sha1_hex(argv[1], tree_sha1) < 0)
|
if (argc < 2 || get_sha1_hex(argv[1], tree_sha1) < 0)
|
||||||
usage(commit_tree_usage);
|
usage(commit_tree_usage);
|
||||||
|
|
||||||
|
setup_git_directory();
|
||||||
|
|
||||||
check_valid(tree_sha1, "tree");
|
check_valid(tree_sha1, "tree");
|
||||||
for (i = 2; i < argc; i += 2) {
|
for (i = 2; i < argc; i += 2) {
|
||||||
char *a, *b;
|
char *a, *b;
|
||||||
|
24
commit.c
24
commit.c
@ -204,6 +204,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
|||||||
unsigned char parent[20];
|
unsigned char parent[20];
|
||||||
struct commit_list **pptr;
|
struct commit_list **pptr;
|
||||||
struct commit_graft *graft;
|
struct commit_graft *graft;
|
||||||
|
unsigned n_refs = 0;
|
||||||
|
|
||||||
if (item->object.parsed)
|
if (item->object.parsed)
|
||||||
return 0;
|
return 0;
|
||||||
@ -214,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));
|
return error("bad tree pointer in commit %s\n", sha1_to_hex(item->object.sha1));
|
||||||
item->tree = lookup_tree(parent);
|
item->tree = lookup_tree(parent);
|
||||||
if (item->tree)
|
if (item->tree)
|
||||||
add_ref(&item->object, &item->tree->object);
|
n_refs++;
|
||||||
bufptr += 46; /* "tree " + "hex sha1" + "\n" */
|
bufptr += 46; /* "tree " + "hex sha1" + "\n" */
|
||||||
pptr = &item->parents;
|
pptr = &item->parents;
|
||||||
|
|
||||||
@ -230,7 +231,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
|||||||
new_parent = lookup_commit(parent);
|
new_parent = lookup_commit(parent);
|
||||||
if (new_parent) {
|
if (new_parent) {
|
||||||
pptr = &commit_list_insert(new_parent, pptr)->next;
|
pptr = &commit_list_insert(new_parent, pptr)->next;
|
||||||
add_ref(&item->object, &new_parent->object);
|
n_refs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (graft) {
|
if (graft) {
|
||||||
@ -241,10 +242,22 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
|||||||
if (!new_parent)
|
if (!new_parent)
|
||||||
continue;
|
continue;
|
||||||
pptr = &commit_list_insert(new_parent, pptr)->next;
|
pptr = &commit_list_insert(new_parent, pptr)->next;
|
||||||
add_ref(&item->object, &new_parent->object);
|
n_refs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item->date = parse_commit_date(bufptr);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,7 +549,7 @@ int count_parents(struct commit * commit)
|
|||||||
void sort_in_topological_order(struct commit_list ** list)
|
void sort_in_topological_order(struct commit_list ** list)
|
||||||
{
|
{
|
||||||
struct commit_list * next = *list;
|
struct commit_list * next = *list;
|
||||||
struct commit_list * work = NULL;
|
struct commit_list * work = NULL, **insert;
|
||||||
struct commit_list ** pptr = list;
|
struct commit_list ** pptr = list;
|
||||||
struct sort_node * nodes;
|
struct sort_node * nodes;
|
||||||
struct sort_node * next_nodes;
|
struct sort_node * next_nodes;
|
||||||
@ -580,11 +593,12 @@ void sort_in_topological_order(struct commit_list ** list)
|
|||||||
* the tips serve as a starting set for the work queue.
|
* the tips serve as a starting set for the work queue.
|
||||||
*/
|
*/
|
||||||
next=*list;
|
next=*list;
|
||||||
|
insert = &work;
|
||||||
while (next) {
|
while (next) {
|
||||||
struct sort_node * node = (struct sort_node *)next->item->object.util;
|
struct sort_node * node = (struct sort_node *)next->item->object.util;
|
||||||
|
|
||||||
if (node->indegree == 0) {
|
if (node->indegree == 0) {
|
||||||
commit_list_insert(next->item, &work);
|
insert = &commit_list_insert(next->item, insert)->next;
|
||||||
}
|
}
|
||||||
next=next->next;
|
next=next->next;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "../cache.h"
|
#include "../git-compat-util.h"
|
||||||
|
|
||||||
void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset)
|
void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset)
|
||||||
{
|
{
|
||||||
|
35
compat/setenv.c
Normal file
35
compat/setenv.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int gitsetenv(const char *name, const char *value, int replace)
|
||||||
|
{
|
||||||
|
int out;
|
||||||
|
size_t namelen, valuelen;
|
||||||
|
char *envstr;
|
||||||
|
|
||||||
|
if (!name || !value) return -1;
|
||||||
|
if (!replace) {
|
||||||
|
char *oldval = NULL;
|
||||||
|
oldval = getenv(name);
|
||||||
|
if (oldval) return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
namelen = strlen(name);
|
||||||
|
valuelen = strlen(value);
|
||||||
|
envstr = malloc((namelen + valuelen + 2));
|
||||||
|
if (!envstr) return -1;
|
||||||
|
|
||||||
|
memcpy(envstr, name, namelen);
|
||||||
|
envstr[namelen] = '=';
|
||||||
|
memcpy(envstr + namelen + 1, value, valuelen);
|
||||||
|
envstr[namelen + valuelen + 1] = 0;
|
||||||
|
|
||||||
|
out = putenv(envstr);
|
||||||
|
/* putenv(3) makes the argument string part of the environment,
|
||||||
|
* and changing that string modifies the environment --- which
|
||||||
|
* means we do not own that storage anymore. Do not free
|
||||||
|
* envstr.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
#include <string.h>
|
#include "../git-compat-util.h"
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
char *gitstrcasestr(const char *haystack, const char *needle)
|
char *gitstrcasestr(const char *haystack, const char *needle)
|
||||||
{
|
{
|
||||||
|
353
config.c
353
config.c
@ -1,9 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* GIT - The information manager from hell
|
||||||
|
*
|
||||||
|
* Copyright (C) Linus Torvalds, 2005
|
||||||
|
* Copyright (C) Johannes Schindelin, 2005
|
||||||
|
*
|
||||||
|
*/
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
#define MAXNAME (256)
|
#define MAXNAME (256)
|
||||||
|
|
||||||
static FILE *config_file;
|
static FILE *config_file;
|
||||||
|
static const char *config_file_name;
|
||||||
static int config_linenr;
|
static int config_linenr;
|
||||||
static int get_next_char(void)
|
static int get_next_char(void)
|
||||||
{
|
{
|
||||||
@ -136,7 +144,7 @@ static int get_base_var(char *name)
|
|||||||
return -1;
|
return -1;
|
||||||
if (c == ']')
|
if (c == ']')
|
||||||
return baselen;
|
return baselen;
|
||||||
if (!isalnum(c))
|
if (!isalnum(c) && c != '.')
|
||||||
return -1;
|
return -1;
|
||||||
if (baselen > MAXNAME / 2)
|
if (baselen > MAXNAME / 2)
|
||||||
return -1;
|
return -1;
|
||||||
@ -179,7 +187,7 @@ static int git_parse_file(config_fn_t fn)
|
|||||||
if (get_value(fn, var, baselen+1) < 0)
|
if (get_value(fn, var, baselen+1) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
die("bad config file line %d", config_linenr);
|
die("bad config file line %d in %s", config_linenr, config_file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_int(const char *name, const char *value)
|
int git_config_int(const char *name, const char *value)
|
||||||
@ -190,7 +198,7 @@ int git_config_int(const char *name, const char *value)
|
|||||||
if (!*end)
|
if (!*end)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
die("bad config value for '%s'", name);
|
die("bad config value for '%s' in %s", name, config_file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_bool(const char *name, const char *value)
|
int git_config_bool(const char *name, const char *value)
|
||||||
@ -214,6 +222,11 @@ int git_default_config(const char *var, const char *value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(var, "core.symrefsonly")) {
|
||||||
|
only_use_symrefs = git_config_bool(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(var, "user.name")) {
|
if (!strcmp(var, "user.name")) {
|
||||||
strncpy(git_default_name, value, sizeof(git_default_name));
|
strncpy(git_default_name, value, sizeof(git_default_name));
|
||||||
return 0;
|
return 0;
|
||||||
@ -224,21 +237,349 @@ int git_default_config(const char *var, const char *value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(var, "i18n.commitencoding")) {
|
||||||
|
strncpy(git_commit_encoding, value, sizeof(git_commit_encoding));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Add other config variables here.. */
|
/* Add other config variables here.. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config(config_fn_t fn)
|
int git_config_from_file(config_fn_t fn, const char *filename)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
FILE *f = fopen(git_path("config"), "r");
|
FILE *f = fopen(filename, "r");
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
if (f) {
|
if (f) {
|
||||||
config_file = f;
|
config_file = f;
|
||||||
|
config_file_name = filename;
|
||||||
config_linenr = 1;
|
config_linenr = 1;
|
||||||
ret = git_parse_file(fn);
|
ret = git_parse_file(fn);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
config_file_name = NULL;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_config(config_fn_t fn)
|
||||||
|
{
|
||||||
|
return git_config_from_file(fn, git_path("config"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)) {
|
||||||
|
free(store.key);
|
||||||
|
|
||||||
|
/* if nothing to unset, error out */
|
||||||
|
if (value == NULL) {
|
||||||
|
close(fd);
|
||||||
|
unlink(lock_file);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
store.key = (char*)key;
|
||||||
|
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);
|
memset(&sa, 0, sizeof sa);
|
||||||
sa.sin_family = he->h_addrtype;
|
sa.sin_family = he->h_addrtype;
|
||||||
sa.sin_port = htons(nport);
|
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) {
|
if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
@ -448,42 +448,162 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
|
|||||||
|
|
||||||
#endif /* NO_IPV6 */
|
#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.
|
* Yeah, yeah, fixme. Need to pass in the heads etc.
|
||||||
*/
|
*/
|
||||||
int git_connect(int fd[2], char *url, const char *prog)
|
int git_connect(int fd[2], char *url, const char *prog)
|
||||||
{
|
{
|
||||||
char command[1024];
|
char command[1024];
|
||||||
char *host, *path;
|
char *host, *path = url;
|
||||||
char *colon;
|
char *colon = NULL;
|
||||||
int pipefd[2][2];
|
int pipefd[2][2];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
enum protocol protocol;
|
enum protocol protocol = PROTO_LOCAL;
|
||||||
|
|
||||||
host = NULL;
|
host = strstr(url, "://");
|
||||||
path = url;
|
if(host) {
|
||||||
colon = strchr(url, ':');
|
*host = '\0';
|
||||||
protocol = PROTO_LOCAL;
|
protocol = get_protocol(url);
|
||||||
if (colon) {
|
host += 3;
|
||||||
*colon = 0;
|
path = strchr(host, '/');
|
||||||
|
}
|
||||||
|
else {
|
||||||
host = url;
|
host = url;
|
||||||
path = colon+1;
|
if ((colon = strchr(host, ':'))) {
|
||||||
protocol = PROTO_SSH;
|
protocol = PROTO_SSH;
|
||||||
if (!memcmp(path, "//", 2)) {
|
*colon = '\0';
|
||||||
char *slash = strchr(path + 2, '/');
|
path = colon + 1;
|
||||||
if (slash) {
|
|
||||||
int nr = slash - path - 2;
|
|
||||||
memmove(path, path+2, nr);
|
|
||||||
path[nr] = 0;
|
|
||||||
protocol = get_protocol(url);
|
|
||||||
host = path;
|
|
||||||
path = slash;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
return git_tcp_connect(fd, prog, host, path);
|
||||||
|
}
|
||||||
|
|
||||||
if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
|
if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
|
||||||
die("unable to create pipe pair for communication");
|
die("unable to create pipe pair for communication");
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#define _XOPEN_SOURCE /* glibc2 needs this */
|
#define _XOPEN_SOURCE 500 /* glibc2 and AIX 5.3L need this */
|
||||||
|
#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
@ -316,6 +317,8 @@ int main(int argc, char **argv)
|
|||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
struct entry *entry;
|
struct entry *entry;
|
||||||
|
|
||||||
|
setup_git_directory();
|
||||||
|
|
||||||
if (argc != 2 || get_sha1(argv[1], sha1))
|
if (argc != 2 || get_sha1(argv[1], sha1))
|
||||||
usage("git-convert-objects <sha1>");
|
usage("git-convert-objects <sha1>");
|
||||||
|
|
||||||
|
19
copy.c
19
copy.c
@ -6,32 +6,27 @@ int copy_fd(int ifd, int ofd)
|
|||||||
int len;
|
int len;
|
||||||
char buffer[8192];
|
char buffer[8192];
|
||||||
char *buf = buffer;
|
char *buf = buffer;
|
||||||
len = read(ifd, buffer, sizeof(buffer));
|
len = xread(ifd, buffer, sizeof(buffer));
|
||||||
if (!len)
|
if (!len)
|
||||||
break;
|
break;
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
int read_error;
|
int read_error;
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
read_error = errno;
|
read_error = errno;
|
||||||
close(ifd);
|
close(ifd);
|
||||||
return error("copy-fd: read returned %s",
|
return error("copy-fd: read returned %s",
|
||||||
strerror(read_error));
|
strerror(read_error));
|
||||||
}
|
}
|
||||||
while (1) {
|
while (len) {
|
||||||
int written = write(ofd, buf, len);
|
int written = xwrite(ofd, buf, len);
|
||||||
if (written > 0) {
|
if (written > 0) {
|
||||||
buf += written;
|
buf += written;
|
||||||
len -= written;
|
len -= written;
|
||||||
if (!len)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (!written)
|
else if (!written)
|
||||||
return error("copy-fd: write returned 0");
|
return error("copy-fd: write returned 0");
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
else
|
||||||
continue;
|
return error("copy-fd: write returned %s",
|
||||||
return error("copy-fd: write returned %s",
|
strerror(errno));
|
||||||
strerror(errno));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(ifd);
|
close(ifd);
|
||||||
|
@ -15,7 +15,7 @@ static int sha1flush(struct sha1file *f, unsigned int count)
|
|||||||
void *buf = f->buffer;
|
void *buf = f->buffer;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret = write(f->fd, buf, count);
|
int ret = xwrite(f->fd, buf, count);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
buf += ret;
|
buf += ret;
|
||||||
count -= ret;
|
count -= ret;
|
||||||
@ -25,8 +25,6 @@ static int sha1flush(struct sha1file *f, unsigned int count)
|
|||||||
}
|
}
|
||||||
if (!ret)
|
if (!ret)
|
||||||
die("sha1 file '%s' write error. Out of diskspace", f->name);
|
die("sha1 file '%s' write error. Out of diskspace", f->name);
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
|
||||||
continue;
|
|
||||||
die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
|
die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
195
daemon.c
195
daemon.c
@ -15,10 +15,11 @@ static int verbose;
|
|||||||
|
|
||||||
static const char daemon_usage[] =
|
static const char daemon_usage[] =
|
||||||
"git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
|
"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 */
|
/* List of acceptable pathname prefixes */
|
||||||
static char **ok_paths = NULL;
|
static char **ok_paths = NULL;
|
||||||
|
static int strict_paths = 0;
|
||||||
|
|
||||||
/* If this is set, git-daemon-export-ok is not required */
|
/* If this is set, git-daemon-export-ok is not required */
|
||||||
static int export_all_trees = 0;
|
static int export_all_trees = 0;
|
||||||
@ -81,69 +82,108 @@ static void loginfo(const char *err, ...)
|
|||||||
va_end(params);
|
va_end(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int path_ok(const char *dir)
|
static int avoid_alias(char *p)
|
||||||
{
|
{
|
||||||
const char *p = dir;
|
|
||||||
char **pp;
|
|
||||||
int sl, ndot;
|
int sl, ndot;
|
||||||
|
|
||||||
/* The pathname here should be an absolute path. */
|
/*
|
||||||
if ( *p++ != '/' )
|
* This resurrects the belts and suspenders paranoia check by HPA
|
||||||
return 0;
|
* done in <435560F7.4080006@zytor.com> thread, now enter_repo()
|
||||||
|
* does not do getcwd() based path canonicalizations.
|
||||||
|
*
|
||||||
|
* sl becomes true immediately after seeing '/' and continues to
|
||||||
|
* be true as long as dots continue after that without intervening
|
||||||
|
* non-dot character.
|
||||||
|
*/
|
||||||
|
if (!p || (*p != '/' && *p != '~'))
|
||||||
|
return -1;
|
||||||
|
sl = 1; ndot = 0;
|
||||||
|
p++;
|
||||||
|
|
||||||
sl = 1; ndot = 0;
|
while (1) {
|
||||||
|
char ch = *p++;
|
||||||
for (;;) {
|
if (sl) {
|
||||||
if ( *p == '.' ) {
|
if (ch == '.')
|
||||||
ndot++;
|
ndot++;
|
||||||
} else if ( *p == '\0' ) {
|
else if (ch == '/') {
|
||||||
/* Reject "." and ".." at the end of the path */
|
if (ndot < 3)
|
||||||
if ( sl && ndot > 0 && ndot < 3 )
|
/* reject //, /./ and /../ */
|
||||||
return 0;
|
return -1;
|
||||||
|
ndot = 0;
|
||||||
/* Otherwise OK */
|
}
|
||||||
break;
|
else if (ch == 0) {
|
||||||
} else if ( *p == '/' ) {
|
if (0 < ndot && ndot < 3)
|
||||||
/* Refuse "", "." or ".." */
|
/* reject /.$ and /..$ */
|
||||||
if ( sl && ndot < 3 )
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sl = ndot = 0;
|
||||||
|
}
|
||||||
|
else if (ch == 0)
|
||||||
|
return 0;
|
||||||
|
else if (ch == '/') {
|
||||||
sl = 1;
|
sl = 1;
|
||||||
ndot = 0;
|
ndot = 0;
|
||||||
} else {
|
|
||||||
sl = ndot = 0;
|
|
||||||
}
|
}
|
||||||
p++;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *path_ok(char *dir)
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
if (avoid_alias(dir)) {
|
||||||
|
logerror("'%s': aliased", dir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = enter_repo(dir, strict_paths);
|
||||||
|
|
||||||
|
if (!path) {
|
||||||
|
logerror("'%s': unable to chdir or not a git archive", dir);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ok_paths && *ok_paths ) {
|
if ( ok_paths && *ok_paths ) {
|
||||||
int ok = 0;
|
char **pp;
|
||||||
int dirlen = strlen(dir);
|
int pathlen = strlen(path);
|
||||||
|
|
||||||
|
/* The validation is done on the paths after enter_repo
|
||||||
|
* appends optional {.git,.git/.git} and friends, but
|
||||||
|
* it does not use getcwd(). So if your /pub is
|
||||||
|
* a symlink to /mnt/pub, you can whitelist /pub and
|
||||||
|
* do not have to say /mnt/pub.
|
||||||
|
* Do not say /pub/.
|
||||||
|
*/
|
||||||
for ( pp = ok_paths ; *pp ; pp++ ) {
|
for ( pp = ok_paths ; *pp ; pp++ ) {
|
||||||
int len = strlen(*pp);
|
int len = strlen(*pp);
|
||||||
if ( len <= dirlen &&
|
if (len <= pathlen &&
|
||||||
!strncmp(*pp, dir, len) &&
|
!memcmp(*pp, path, len) &&
|
||||||
(dir[len] == '/' || dir[len] == '\0') ) {
|
(path[len] == '\0' ||
|
||||||
ok = 1;
|
(!strict_paths && path[len] == '/')))
|
||||||
break;
|
return path;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ( !ok )
|
else {
|
||||||
return 0; /* Path not in whitelist */
|
/* 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)) {
|
/* Timeout as string */
|
||||||
errno = EACCES;
|
char timeout_buf[64];
|
||||||
return -1;
|
const char *path;
|
||||||
}
|
|
||||||
|
|
||||||
if ( chdir(dir) )
|
loginfo("Request for '%s'", dir);
|
||||||
|
|
||||||
|
if (!(path = path_ok(dir)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -152,45 +192,17 @@ static int set_dir(const char *dir)
|
|||||||
* We want a readable HEAD, usable "objects" directory, and
|
* We want a readable HEAD, usable "objects" directory, and
|
||||||
* a "git-daemon-export-ok" flag that says that the other side
|
* a "git-daemon-export-ok" flag that says that the other side
|
||||||
* is ok with us doing this.
|
* 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)) {
|
if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
|
||||||
|
logerror("'%s': repository not exported.", path);
|
||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return -1;
|
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
|
* We'll ignore SIGTERM from now on, we have a
|
||||||
* good client.
|
* good client.
|
||||||
@ -216,7 +228,7 @@ static int execute(void)
|
|||||||
if (len && line[len-1] == '\n')
|
if (len && line[len-1] == '\n')
|
||||||
line[--len] = 0;
|
line[--len] = 0;
|
||||||
|
|
||||||
if (!strncmp("git-upload-pack /", line, 17))
|
if (!strncmp("git-upload-pack ", line, 16))
|
||||||
return upload(line+16);
|
return upload(line+16);
|
||||||
|
|
||||||
logerror("Protocol error: '%s'", line);
|
logerror("Protocol error: '%s'", line);
|
||||||
@ -510,8 +522,14 @@ static int socksetup(int port, int **socklist_p)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (listen(sockfd, 5) < 0) {
|
||||||
|
close(sockfd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
*socklist_p = xmalloc(sizeof(int));
|
*socklist_p = xmalloc(sizeof(int));
|
||||||
**socklist_p = sockfd;
|
**socklist_p = sockfd;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -594,6 +612,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (!strcmp(arg, "--inetd")) {
|
if (!strcmp(arg, "--inetd")) {
|
||||||
inetd_mode = 1;
|
inetd_mode = 1;
|
||||||
|
log_syslog = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--verbose")) {
|
if (!strcmp(arg, "--verbose")) {
|
||||||
@ -602,7 +621,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (!strcmp(arg, "--syslog")) {
|
if (!strcmp(arg, "--syslog")) {
|
||||||
log_syslog = 1;
|
log_syslog = 1;
|
||||||
openlog("git-daemon", 0, LOG_DAEMON);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--export-all")) {
|
if (!strcmp(arg, "--export-all")) {
|
||||||
@ -611,9 +629,15 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (!strncmp(arg, "--timeout=", 10)) {
|
if (!strncmp(arg, "--timeout=", 10)) {
|
||||||
timeout = atoi(arg+10);
|
timeout = atoi(arg+10);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (!strncmp(arg, "--init-timeout=", 15)) {
|
if (!strncmp(arg, "--init-timeout=", 15)) {
|
||||||
init_timeout = atoi(arg+15);
|
init_timeout = atoi(arg+15);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(arg, "--strict-paths")) {
|
||||||
|
strict_paths = 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--")) {
|
if (!strcmp(arg, "--")) {
|
||||||
ok_paths = &argv[i+1];
|
ok_paths = &argv[i+1];
|
||||||
@ -626,10 +650,21 @@ int main(int argc, char **argv)
|
|||||||
usage(daemon_usage);
|
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) {
|
if (inetd_mode) {
|
||||||
fclose(stderr); //FIXME: workaround
|
fclose(stderr); //FIXME: workaround
|
||||||
return execute();
|
return execute();
|
||||||
} else {
|
|
||||||
return serve(port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return serve(port);
|
||||||
}
|
}
|
||||||
|
186
date.c
186
date.c
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ static const char *month_names[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char *weekday_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);
|
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);
|
||||||
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user