Compare commits
361 Commits
Author | SHA1 | Date | |
---|---|---|---|
bd9ca0baff | |||
4bbdfab766 | |||
c5e09c1fbe | |||
024701f1d8 | |||
0dbc4e89bb | |||
ef1af9d9af | |||
d7ee090d0d | |||
2b796360ac | |||
070879ca93 | |||
5b766ea901 | |||
af8c28e145 | |||
c611db196a | |||
4890f62bc0 | |||
7162dff3dd | |||
6932c78cb4 | |||
16139f9035 | |||
1536dd9c61 | |||
7bbdeaa969 | |||
21fcd1bdea | |||
98deeaa82f | |||
c548cf4ee0 | |||
5ee2ad654b | |||
29e55cd5ad | |||
3f6726e1f1 | |||
9ae6be8016 | |||
9da5c2f0d7 | |||
39556fbdad | |||
e7ad4a9c3c | |||
4d44cb195a | |||
d416df8869 | |||
297a1aadbe | |||
cf7bb589af | |||
4dc870d90c | |||
91c7674371 | |||
d60fc1c864 | |||
67d42212ff | |||
0a798076b8 | |||
ce1610ead6 | |||
5b23683251 | |||
147cf31738 | |||
ee63802422 | |||
701ca744e3 | |||
47e013f920 | |||
dfdd309e57 | |||
d19e06fa8f | |||
deb989b57d | |||
4e783b41e0 | |||
3904848c6e | |||
53f313897e | |||
66f04f38f4 | |||
90768daaa0 | |||
5a798fb57f | |||
130fcca63f | |||
8389b52b2a | |||
1cb303872a | |||
1b1fdf8c2f | |||
8bc5c04a71 | |||
cc55aaec38 | |||
85a97d4e10 | |||
3598a30808 | |||
4462731e05 | |||
b77b02785d | |||
418c4c7bce | |||
2454c962fb | |||
9843a1f6fd | |||
960c7021b3 | |||
f22fd75c6a | |||
a2c641c4ab | |||
12db4852de | |||
a8c44537fe | |||
45392a648d | |||
e3c3a550d4 | |||
9ad0a93330 | |||
2718435b7b | |||
603968d22b | |||
1955fabf41 | |||
363f24c936 | |||
a3f583cbf7 | |||
7982d74e1c | |||
7b934ec015 | |||
09db444fdb | |||
80d48ac623 | |||
df9892ffce | |||
4abd89648e | |||
ec0bdb6f1e | |||
04fe2a1706 | |||
9523a4c2fc | |||
7334f06ce6 | |||
2d310d8a01 | |||
8361e1d4d3 | |||
1fda3d557b | |||
c0c74a88f9 | |||
0601dbe178 | |||
8fcf7f9af5 | |||
f7a3d33f0f | |||
46dc941246 | |||
f16706cc59 | |||
b469d8b6f7 | |||
30d08b34aa | |||
d366c70376 | |||
6bfb27a0c5 | |||
97f58b785d | |||
008bb6ea69 | |||
985cb9cc58 | |||
823bcd6edc | |||
fd4b1d2193 | |||
bf1c32bdec | |||
3c39e9bdeb | |||
6a1f79c1f1 | |||
884944239f | |||
2d49711512 | |||
d9e2e12700 | |||
cb754fdf5a | |||
8233340ce6 | |||
3af06987eb | |||
e36f8b6034 | |||
c8568e139e | |||
7ec57556b2 | |||
50f9a858ad | |||
1a5c3a01aa | |||
807f900a73 | |||
c3f9281255 | |||
5207234a68 | |||
b8bc67cef3 | |||
1506fc34f7 | |||
d41df15e69 | |||
5179c8a54f | |||
36b5b3c659 | |||
8fedb83c05 | |||
f0fff36e82 | |||
075dd8ee54 | |||
4353f38616 | |||
d37fd03222 | |||
34801cab72 | |||
939aabbf7d | |||
addafaf92e | |||
b33aba5184 | |||
6b1ddbdd6e | |||
f2d4227530 | |||
3815f423ae | |||
62a604ba1c | |||
1dc4fb84b5 | |||
b2d4c56f2f | |||
d50125085a | |||
46a6c2620b | |||
93b74bca86 | |||
461cf59f89 | |||
ea726d02e9 | |||
3ec1909fda | |||
8828cdcb44 | |||
263eee29e9 | |||
e228340961 | |||
5290a0f812 | |||
d8f4790e6f | |||
af3feefa1d | |||
6b94f1e404 | |||
767e130915 | |||
2111168f31 | |||
ca182053c7 | |||
1ecc18e4fc | |||
b3bf974cab | |||
374dfaa2e3 | |||
e974c9ab03 | |||
a8608db5e9 | |||
2796a9de31 | |||
521698b153 | |||
731043fd4d | |||
5ea06e2014 | |||
fc5be4fdaa | |||
205df2796d | |||
73e5456ed3 | |||
d8f6b342ae | |||
92643a27cc | |||
016fb48bc4 | |||
96b086d618 | |||
2c620a1ad1 | |||
e6489a1bdf | |||
4fb66a62ee | |||
87e80c4b5f | |||
941c944999 | |||
41e79c9559 | |||
8a3ee7c314 | |||
dcc6e28f70 | |||
76b927f19f | |||
927a503cd0 | |||
5b2bcc7b2d | |||
0bdd79af62 | |||
5df9140c92 | |||
63be37b06f | |||
35a730f01c | |||
bdc37f5a81 | |||
eff351c957 | |||
a325957062 | |||
8278ac2f4a | |||
8e76c79f4a | |||
e72c9f5c54 | |||
abb9ae95f4 | |||
e7555785f4 | |||
2fabd21733 | |||
949964c4af | |||
c4e804bbf0 | |||
3a75f67401 | |||
e921fb82cf | |||
e93ec6f9d8 | |||
5c7d3c9507 | |||
42301e34a2 | |||
fec9ebf16c | |||
8a263aeb4f | |||
181dc77695 | |||
0620db36f8 | |||
8cd1621149 | |||
ffd97f3a35 | |||
7cb038a692 | |||
ae4a35261d | |||
ee3d299e93 | |||
d425142e2a | |||
1aa68d6735 | |||
ebedc31952 | |||
54f9734ec8 | |||
98efc8f3d8 | |||
36383a3df3 | |||
8a1a120c55 | |||
980d8ce551 | |||
9e9b26751a | |||
1be0659efc | |||
19205acfc2 | |||
429608fc36 | |||
b42934d611 | |||
77cb17e940 | |||
59617ebb74 | |||
e99c2fbdda | |||
a0dfb48af7 | |||
cb95bf488b | |||
c884dd9a54 | |||
c2bc6e404d | |||
4dc00021f7 | |||
87758f975b | |||
2c817df25d | |||
4c34a2c555 | |||
8c23b6fae2 | |||
a94d9948da | |||
5a25b4a66e | |||
0f76f52621 | |||
cfa6d70bd4 | |||
0de62e5985 | |||
78ff5cf6b5 | |||
d5a6aafc90 | |||
c2bdd6afe2 | |||
eb858c60d7 | |||
181129d24c | |||
5a2282de13 | |||
e77f489edf | |||
b91db2707a | |||
77f1055ca7 | |||
b21c31c9a5 | |||
f8f9c73c7d | |||
78c2cff61f | |||
9eafb7bad1 | |||
0907fedbee | |||
657907e76e | |||
9518eb2629 | |||
03febf99bc | |||
8fc11b5aa9 | |||
6f2eacfeb2 | |||
013049c985 | |||
5f815e5922 | |||
36071af305 | |||
3ac0ebbba4 | |||
8f1d2e6f49 | |||
3be7098ce4 | |||
7d0e65b892 | |||
476e801111 | |||
34c99da2a4 | |||
576cfc86fc | |||
026351a035 | |||
5df466c507 | |||
92e802c6cc | |||
c1fe2fe4fe | |||
da6bf70ebf | |||
2ed8e622bf | |||
2961e0ee8b | |||
6ce183216d | |||
aa66c7ec77 | |||
81214e4ddf | |||
353ce81597 | |||
6ff0b1c56c | |||
2ccd2027b0 | |||
10ae7d86c1 | |||
b484ef28fb | |||
e58b97af31 | |||
31f883d1b8 | |||
50b4e0c178 | |||
b6ae5409ea | |||
88fb958baa | |||
d9e08be9d5 | |||
781411ed46 | |||
7f272ca80c | |||
b73cebf437 | |||
0a15217184 | |||
8b32572c74 | |||
4e7a2eccc2 | |||
82f9d58a39 | |||
89438677ab | |||
f1ec72ba1e | |||
58e3fb40f7 | |||
17dff84b5e | |||
cfee10a773 | |||
9b88fcef7d | |||
c06818e20a | |||
64deb858b0 | |||
2d9e7c9f90 | |||
4cdf78bf96 | |||
635d413430 | |||
908e5310b9 | |||
36cd2cc7d9 | |||
e9add36007 | |||
8eafa3da62 | |||
08337a97a2 | |||
36de72aa9d | |||
e5f5219a4f | |||
975b31dc6e | |||
c97451ce09 | |||
7e4a2a8483 | |||
7d6fb370bc | |||
2ed7542fad | |||
b74ed49735 | |||
af6e277c5e | |||
457f06d68e | |||
2414721b19 | |||
6ab58895cd | |||
ac44f3e7c0 | |||
9a84074d08 | |||
695bf722da | |||
056211053b | |||
bb5ebed731 | |||
c5ced64578 | |||
d0d14cf33d | |||
a69dd585fc | |||
104f3e03c0 | |||
797bd6f490 | |||
5f94c730f3 | |||
c10d634518 | |||
c63da8d8e8 | |||
e6c310fd0d | |||
1e80e04492 | |||
a14c225661 | |||
e99fcf96de | |||
69310a34cb | |||
356bece0a2 | |||
9b15770220 | |||
ebc12ce5bf | |||
7246ed438c | |||
6d016c9c7f | |||
724b511d4f | |||
c894168631 | |||
f4a11066cf | |||
2a212746f4 | |||
8d712aafd2 | |||
8ac4838af4 | |||
50e7b06730 | |||
5d9d11db3c |
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
GIT-VERSION-FILE
|
||||||
git
|
git
|
||||||
git-add
|
git-add
|
||||||
git-am
|
git-am
|
||||||
@ -27,6 +28,7 @@ git-diff-files
|
|||||||
git-diff-index
|
git-diff-index
|
||||||
git-diff-stages
|
git-diff-stages
|
||||||
git-diff-tree
|
git-diff-tree
|
||||||
|
git-describe
|
||||||
git-fetch
|
git-fetch
|
||||||
git-fetch-pack
|
git-fetch-pack
|
||||||
git-findtags
|
git-findtags
|
||||||
@ -76,6 +78,7 @@ git-relink
|
|||||||
git-repack
|
git-repack
|
||||||
git-repo-config
|
git-repo-config
|
||||||
git-request-pull
|
git-request-pull
|
||||||
|
git-rerere
|
||||||
git-reset
|
git-reset
|
||||||
git-resolve
|
git-resolve
|
||||||
git-rev-list
|
git-rev-list
|
||||||
@ -86,6 +89,7 @@ git-send-pack
|
|||||||
git-sh-setup
|
git-sh-setup
|
||||||
git-shell
|
git-shell
|
||||||
git-shortlog
|
git-shortlog
|
||||||
|
git-show
|
||||||
git-show-branch
|
git-show-branch
|
||||||
git-show-index
|
git-show-index
|
||||||
git-ssh-fetch
|
git-ssh-fetch
|
||||||
@ -119,3 +123,5 @@ git-core.spec
|
|||||||
*.exe
|
*.exe
|
||||||
libgit.a
|
libgit.a
|
||||||
*.o
|
*.o
|
||||||
|
*.py[co]
|
||||||
|
config.mak
|
||||||
|
1
Documentation/.gitignore
vendored
1
Documentation/.gitignore
vendored
@ -4,3 +4,4 @@
|
|||||||
*.7
|
*.7
|
||||||
howto-index.txt
|
howto-index.txt
|
||||||
doc.dep
|
doc.dep
|
||||||
|
README
|
||||||
|
@ -4,6 +4,7 @@ MAN7_TXT=git.txt
|
|||||||
DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT))
|
DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT))
|
||||||
|
|
||||||
ARTICLES = tutorial
|
ARTICLES = tutorial
|
||||||
|
ARTICLES += core-tutorial
|
||||||
ARTICLES += cvs-migration
|
ARTICLES += cvs-migration
|
||||||
ARTICLES += diffcore
|
ARTICLES += diffcore
|
||||||
ARTICLES += howto-index
|
ARTICLES += howto-index
|
||||||
@ -61,11 +62,14 @@ doc.dep : $(wildcard *.txt) build-docdep.perl
|
|||||||
|
|
||||||
-include doc.dep
|
-include doc.dep
|
||||||
|
|
||||||
git.7: ../README
|
git.7: README
|
||||||
|
|
||||||
|
README: ../README
|
||||||
|
cp $< $@
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep
|
rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep README
|
||||||
|
|
||||||
%.html : %.txt
|
%.html : %.txt
|
||||||
asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<
|
asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<
|
||||||
@ -76,7 +80,7 @@ clean:
|
|||||||
%.xml : %.txt
|
%.xml : %.txt
|
||||||
asciidoc -b docbook -d manpage -f asciidoc.conf $<
|
asciidoc -b docbook -d manpage -f asciidoc.conf $<
|
||||||
|
|
||||||
git.html: git.txt ../README
|
git.html: git.txt README
|
||||||
|
|
||||||
glossary.html : glossary.txt sort_glossary.pl
|
glossary.html : glossary.txt sort_glossary.pl
|
||||||
cat $< | \
|
cat $< | \
|
||||||
|
1722
Documentation/core-tutorial.txt
Normal file
1722
Documentation/core-tutorial.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,126 +1,182 @@
|
|||||||
git for CVS users
|
git for CVS users
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Ok, so you're a CVS user. That's ok, it's a treatable condition, and the
|
So you're a CVS user. That's ok, it's a treatable condition. The job of
|
||||||
first step to recovery is admitting you have a problem. The fact that
|
this document is to put you on the road to recovery, by helping you
|
||||||
you are reading this file means that you may be well on that path
|
convert an existing cvs repository to git, and by showing you how to use a
|
||||||
already.
|
git repository in a cvs-like fashion.
|
||||||
|
|
||||||
The thing about CVS is that it absolutely sucks as a source control
|
Some basic familiarity with git is required. This
|
||||||
manager, and you'll thus be happy with almost anything else. git,
|
link:tutorial.html[tutorial introduction to git] should be sufficient.
|
||||||
however, may be a bit 'too' different (read: "good") for your taste, and
|
|
||||||
does a lot of things differently.
|
|
||||||
|
|
||||||
One particular suckage of CVS is very hard to work around: CVS is
|
First, note some ways that git differs from CVS:
|
||||||
basically a tool for tracking 'file' history, while git is a tool for
|
|
||||||
tracking 'project' history. This sometimes causes problems if you are
|
|
||||||
used to doing very strange things in CVS, in particular if you're doing
|
|
||||||
things like making branches of just a subset of the project. git can't
|
|
||||||
track that, since git never tracks things on the level of an individual
|
|
||||||
file, only on the whole project level.
|
|
||||||
|
|
||||||
The good news is that most people don't do that, and in fact most sane
|
* Commits are atomic and project-wide, not per-file as in CVS.
|
||||||
people think it's a bug in CVS that makes it tag (and check in changes)
|
|
||||||
one file at a time. So most projects you'll ever see will use CVS
|
|
||||||
'as if' it was sane. In which case you'll find it very easy indeed to
|
|
||||||
move over to git.
|
|
||||||
|
|
||||||
First off: this is not a git tutorial. See
|
* Offline work is supported: you can make multiple commits locally,
|
||||||
link:tutorial.html[Documentation/tutorial.txt] for how git
|
then submit them when you're ready.
|
||||||
actually works. This is more of a random collection of gotcha's
|
|
||||||
and notes on converting from CVS to git.
|
|
||||||
|
|
||||||
Second: CVS has the notion of a "repository" as opposed to the thing
|
* Branching is fast and easy.
|
||||||
that you're actually working in (your working directory, or your
|
|
||||||
"checked out tree"). git does not have that notion at all, and all git
|
|
||||||
working directories 'are' the repositories. However, you can easily
|
|
||||||
emulate the CVS model by having one special "global repository", which
|
|
||||||
people can synchronize with. See details later, but in the meantime
|
|
||||||
just keep in mind that with git, every checked out working tree will
|
|
||||||
have a full revision control history of its own.
|
|
||||||
|
|
||||||
|
* Every working tree contains a repository with a full copy of the
|
||||||
|
project history, and no repository is inherently more important than
|
||||||
|
any other. However, you can emulate the CVS model by designating a
|
||||||
|
single shared repository which people can synchronize with; see below
|
||||||
|
for details.
|
||||||
|
|
||||||
Importing a CVS archive
|
Importing a CVS archive
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Ok, you have an old project, and you want to at least give git a chance
|
First, install version 2.1 or higher of cvsps from
|
||||||
to see how it performs. The first thing you want to do (after you've
|
link:http://www.cobite.com/cvsps/[http://www.cobite.com/cvsps/] and make
|
||||||
gone through the git tutorial, and generally familiarized yourself with
|
sure it is in your path. The magic command line is then
|
||||||
how to commit stuff etc in git) is to create a git'ified version of your
|
|
||||||
CVS archive.
|
|
||||||
|
|
||||||
Happily, that's very easy indeed. git will do it for you, although git
|
-------------------------------------------
|
||||||
will need the help of a program called "cvsps":
|
$ git cvsimport -v -d <cvsroot> -C <destination> <module>
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
http://www.cobite.com/cvsps/
|
This puts a git archive of the named CVS module in the directory
|
||||||
|
<destination>, which will be created if necessary. The -v option makes
|
||||||
|
the conversion script very chatty.
|
||||||
|
|
||||||
which is not actually related to git at all, but which makes CVS usage
|
The import checks out from CVS every revision of every file. Reportedly
|
||||||
look almost sane (ie you almost certainly want to have it even if you
|
cvsimport can average some twenty revisions per second, so for a
|
||||||
decide to stay with CVS). However, git will want 'at least' version 2.1
|
medium-sized project this should not take more than a couple of minutes.
|
||||||
of cvsps (available at the address above), and in fact will currently
|
Larger projects or remote repositories may take longer.
|
||||||
refuse to work with anything else.
|
|
||||||
|
|
||||||
Once you've gotten (and installed) cvsps, you may or may not want to get
|
The main trunk is stored in the git branch named `origin`, and additional
|
||||||
any more familiar with it, but make sure it is in your path. After that,
|
CVS branches are stored in git branches with the same names. The most
|
||||||
the magic command line is
|
recent version of the main trunk is also left checked out on the `master`
|
||||||
|
branch, so you can start adding your own changes right away.
|
||||||
|
|
||||||
git cvsimport -v -d <cvsroot> -C <destination> <module>
|
The import is incremental, so if you call it again next month it will
|
||||||
|
fetch any CVS updates that have been made in the meantime. For this to
|
||||||
|
work, you must not modify the imported branches; instead, create new
|
||||||
|
branches for your own changes, and merge in the imported branches as
|
||||||
|
necessary.
|
||||||
|
|
||||||
which will do exactly what you'd think it does: it will create a git
|
Development Models
|
||||||
archive of the named CVS module. The new archive will be created in the
|
------------------
|
||||||
subdirectory named <destination>; it'll be created if it doesn't exist.
|
|
||||||
Default is the local directory.
|
|
||||||
|
|
||||||
It can take some time to actually do the conversion for a large archive
|
CVS users are accustomed to giving a group of developers commit access to
|
||||||
since it involves checking out from CVS every revision of every file,
|
a common repository. In the next section we'll explain how to do this
|
||||||
and the conversion script is reasonably chatty unless you omit the '-v'
|
with git. However, the distributed nature of git allows other development
|
||||||
option, but on some not very scientific tests it averaged about twenty
|
models, and you may want to first consider whether one of them might be a
|
||||||
revisions per second, so a medium-sized project should not take more
|
better fit for your project.
|
||||||
than a couple of minutes. For larger projects or remote repositories,
|
|
||||||
the process may take longer.
|
|
||||||
|
|
||||||
After the (initial) import is done, the CVS archive's current head
|
For example, you can choose a single person to maintain the project's
|
||||||
revision will be checked out -- thus, you can start adding your own
|
primary public repository. Other developers then clone this repository
|
||||||
changes right away.
|
and each work in their own clone. When they have a series of changes that
|
||||||
|
they're happy with, they ask the maintainer to pull from the branch
|
||||||
|
containing the changes. The maintainer reviews their changes and pulls
|
||||||
|
them into the primary repository, which other developers pull from as
|
||||||
|
necessary to stay coordinated. The Linux kernel and other projects use
|
||||||
|
variants of this model.
|
||||||
|
|
||||||
The import is incremental, i.e. if you call it again next month it'll
|
With a small group, developers may just pull changes from each other's
|
||||||
fetch any CVS updates that have been happening in the meantime. The
|
repositories without the need for a central maintainer.
|
||||||
cut-off is date-based, so don't change the branches that were imported
|
|
||||||
from CVS.
|
|
||||||
|
|
||||||
You can merge those updates (or, in fact, a different CVS branch) into
|
Emulating the CVS Development Model
|
||||||
your main branch:
|
-----------------------------------
|
||||||
|
|
||||||
git resolve HEAD origin "merge with current CVS HEAD"
|
Start with an ordinary git working directory containing the project, and
|
||||||
|
remove the checked-out files, keeping just the bare .git directory:
|
||||||
|
|
||||||
The HEAD revision from CVS is named "origin", not "HEAD", because git
|
------------------------------------------------
|
||||||
already uses "HEAD". (If you don't like 'origin', use cvsimport's
|
$ mv project/.git /pub/repo.git
|
||||||
'-o' option to change it.)
|
$ rm -r project/
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
Next, give every team member read/write access to this repository. One
|
||||||
|
easy way to do this is to give all the team members ssh access to the
|
||||||
|
machine where the repository is hosted. If you don't want to give them a
|
||||||
|
full shell on the machine, there is a restricted shell which only allows
|
||||||
|
users to do git pushes and pulls; see gitlink:git-shell[1].
|
||||||
|
|
||||||
Emulating CVS behaviour
|
Put all the committers should in the same group, and make the repository
|
||||||
-----------------------
|
writable by that group:
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
$ chgrp -R $group repo.git
|
||||||
|
$ find repo.git -mindepth 1 -type d |xargs chmod ug+rwx,g+s
|
||||||
|
$ GIT_DIR=repo.git git repo-config core.sharedrepository true
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
So, by now you are convinced you absolutely want to work with git, but
|
Make sure committers have a umask of at most 027, so that the directories
|
||||||
at the same time you absolutely have to have a central repository.
|
they create are writable and searchable by other group members.
|
||||||
Step back and think again. Okay, you still need a single central
|
|
||||||
repository? There are several ways to go about that:
|
|
||||||
|
|
||||||
1. Designate a person responsible to pull all branches. Make the
|
Suppose this repository is now set up in /pub/repo.git on the host
|
||||||
repository of this person public, and make every team member
|
foo.com. Then as an individual commiter you can clone the shared
|
||||||
pull regularly from it.
|
repository:
|
||||||
|
|
||||||
2. Set up a public repository with read/write access for every team
|
------------------------------------------------
|
||||||
member. Use "git pull/push" as you used "cvs update/commit". Be
|
$ git clone foo.com:/pub/repo.git/ my-project
|
||||||
sure that your repository is up to date before pushing, just
|
$ cd my-project
|
||||||
like you used to do with "cvs commit"; your push will fail if
|
------------------------------------------------
|
||||||
what you are pushing is not up to date.
|
|
||||||
|
|
||||||
3. Make the repository of every team member public. It is the
|
and hack away. The equivalent of `cvs update` is
|
||||||
responsibility of each single member to pull from every other
|
|
||||||
team member.
|
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
$ git pull origin
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
which merges in any work that others might have done since the clone
|
||||||
|
operation.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
================================
|
||||||
|
The first `git clone` places the following in the
|
||||||
|
`my-project/.git/remotes/origin` file, and that's why the previous step
|
||||||
|
and the next step both work.
|
||||||
|
------------
|
||||||
|
URL: foo.com:/pub/project.git/ my-project
|
||||||
|
Pull: master:origin
|
||||||
|
------------
|
||||||
|
================================
|
||||||
|
|
||||||
|
You can update the shared repository with your changes using:
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
$ git push origin master
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
If someone else has updated the repository more recently, `git push`, like
|
||||||
|
`cvs commit`, will complain, in which case you must pull any changes
|
||||||
|
before attempting the push again.
|
||||||
|
|
||||||
|
In the `git push` command above we specify the name of the remote branch
|
||||||
|
to update (`master`). If we leave that out, `git push` tries to update
|
||||||
|
any branches in the remote repository that have the same name as a branch
|
||||||
|
in the local repository. So the last `push` can be done with either of:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git push origin
|
||||||
|
$ git push repo.shared.xz:/pub/scm/project.git/
|
||||||
|
------------
|
||||||
|
|
||||||
|
as long as the shared repository does not have any branches
|
||||||
|
other than `master`.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
============
|
||||||
|
Because of this behaviour, if the shared repository and the developer's
|
||||||
|
repository both have branches named `origin`, then a push like the above
|
||||||
|
attempts to update the `origin` branch in the shared repository from the
|
||||||
|
developer's `origin` branch. The results may be unexpected, so it's
|
||||||
|
usually best to remove any branch named `origin` from the shared
|
||||||
|
repository.
|
||||||
|
============
|
||||||
|
|
||||||
|
Advanced Shared Repository Management
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Git allows you to specify scripts called "hooks" to be run at certain
|
||||||
|
points. You can use these, for example, to send all commits to the shared
|
||||||
|
repository to a mailing list. See link:hooks.txt[Hooks used by git].
|
||||||
|
|
||||||
|
You can enforce finer grained permissions using update hooks. See
|
||||||
|
link:howto/update-hook-example.txt[Controlling access to branches using
|
||||||
|
update hooks].
|
||||||
|
|
||||||
CVS annotate
|
CVS annotate
|
||||||
------------
|
------------
|
||||||
@ -138,7 +194,7 @@ mailing list archives for details).
|
|||||||
git has a couple of alternatives, though, that you may find sufficient
|
git has a couple of alternatives, though, that you may find sufficient
|
||||||
or even superior depending on your use. One is called "git-whatchanged"
|
or even superior depending on your use. One is called "git-whatchanged"
|
||||||
(for obvious reasons) and the other one is called "pickaxe" ("a tool for
|
(for obvious reasons) and the other one is called "pickaxe" ("a tool for
|
||||||
the software archeologist").
|
the software archaeologist").
|
||||||
|
|
||||||
The "git-whatchanged" script is a truly trivial script that can give you
|
The "git-whatchanged" script is a truly trivial script that can give you
|
||||||
a good overview of what has changed in a file or a directory (or an
|
a good overview of what has changed in a file or a directory (or an
|
||||||
|
@ -117,7 +117,7 @@ git specific extension to diff format
|
|||||||
What -p option produces is slightly different from the
|
What -p option produces is slightly different from the
|
||||||
traditional diff format.
|
traditional diff format.
|
||||||
|
|
||||||
1. It is preceeded with a "git diff" header, that looks like
|
1. It is preceded with a "git diff" header, that looks like
|
||||||
this:
|
this:
|
||||||
|
|
||||||
diff --git a/file1 b/file2
|
diff --git a/file1 b/file2
|
||||||
@ -146,3 +146,52 @@ the file that rename/copy produces, respectively.
|
|||||||
|
|
||||||
3. TAB, LF, and backslash characters in pathnames are
|
3. TAB, LF, and backslash characters in pathnames are
|
||||||
represented as `\t`, `\n`, and `\\`, respectively.
|
represented as `\t`, `\n`, and `\\`, respectively.
|
||||||
|
|
||||||
|
|
||||||
|
combined diff format
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
git-diff-tree and git-diff-files can take '-c' or '--cc' option
|
||||||
|
to produce 'combined diff', which looks like this:
|
||||||
|
|
||||||
|
------------
|
||||||
|
diff --combined describe.c
|
||||||
|
@@@ +98,7 @@@
|
||||||
|
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- static void describe(char *arg)
|
||||||
|
-static void describe(struct commit *cmit, int last_one)
|
||||||
|
++static void describe(char *arg, int last_one)
|
||||||
|
{
|
||||||
|
+ unsigned char sha1[20];
|
||||||
|
+ struct commit *cmit;
|
||||||
|
------------
|
||||||
|
|
||||||
|
Unlike the traditional 'unified' diff format, which shows two
|
||||||
|
files A and B with a single column that has `-` (minus --
|
||||||
|
appears in A but removed in B), `+` (plus -- missing in A but
|
||||||
|
added to B), or ` ` (space -- unchanged) prefix, this format
|
||||||
|
compares two or more files file1, file2,... with one file X, and
|
||||||
|
shows how X differs from each of fileN. One column for each of
|
||||||
|
fileN is prepended to the output line to note how X's line is
|
||||||
|
different from it.
|
||||||
|
|
||||||
|
A `-` character in the column N means that the line appears in
|
||||||
|
fileN but it does not appear in the last file. A `+` character
|
||||||
|
in the column N means that the line appears in the last file,
|
||||||
|
and fileN does not have that line.
|
||||||
|
|
||||||
|
In the above example output, the function signature was changed
|
||||||
|
from both files (hence two `-` removals from both file1 and
|
||||||
|
file2, plus `++` to mean one line that was added does not appear
|
||||||
|
in either file1 nor file2). Also two other lines are the same
|
||||||
|
from file1 but do not appear in file2 (hence prefixed with ` +`).
|
||||||
|
|
||||||
|
When shown by `git diff-tree -c`, it compares the parents of a
|
||||||
|
merge commit with the merge result (i.e. file1..fileN are the
|
||||||
|
parents). When shown by `git diff-files -c`, it compares the
|
||||||
|
two unresolved merge parents with the working tree file
|
||||||
|
(i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka
|
||||||
|
"their version").
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
--abbrev[=<n>]::
|
--abbrev[=<n>]::
|
||||||
Instead of showing the full 40-byte hexadecimal object
|
Instead of showing the full 40-byte hexadecimal object
|
||||||
name in diff-raw format output and diff-tree header
|
name in diff-raw format output and diff-tree header
|
||||||
lines, show only handful dhexigits prefix. This is
|
lines, show only handful hexdigits prefix. This is
|
||||||
independent of --full-index option above, which controls
|
independent of --full-index option above, which controls
|
||||||
the diff-patch output format. Non default number of
|
the diff-patch output format. Non default number of
|
||||||
digits can be specified with --abbrev=<n>.
|
digits can be specified with --abbrev=<n>.
|
||||||
@ -35,6 +35,17 @@
|
|||||||
-C::
|
-C::
|
||||||
Detect copies as well as renames.
|
Detect copies as well as renames.
|
||||||
|
|
||||||
|
--diff-filter=[ACDMRTUXB*]::
|
||||||
|
Select only files that are Added (`A`), Copied (`C`),
|
||||||
|
Deleted (`D`), Modified (`M`), Renamed (`R`), have their
|
||||||
|
type (mode) changed (`T`), are Unmerged (`U`), are
|
||||||
|
Unknown (`X`), or have had their pairing Broken (`B`).
|
||||||
|
Any combination of the filter characters may be used.
|
||||||
|
When `*` (All-or-none) is added to the combination, all
|
||||||
|
paths are selected if there is any file that matches
|
||||||
|
other criteria in the comparison; if there is no file
|
||||||
|
that matches other criteria, nothing is selected.
|
||||||
|
|
||||||
--find-copies-harder::
|
--find-copies-harder::
|
||||||
For performance reasons, by default, -C option finds copies only
|
For performance reasons, by default, -C option finds copies only
|
||||||
if the original file of the copy was modified in the same
|
if the original file of the copy was modified in the same
|
||||||
|
@ -3,6 +3,12 @@
|
|||||||
existing contents of `.git/FETCH_HEAD`. Without this
|
existing contents of `.git/FETCH_HEAD`. Without this
|
||||||
option old data in `.git/FETCH_HEAD` will be overwritten.
|
option old data in `.git/FETCH_HEAD` will be overwritten.
|
||||||
|
|
||||||
|
\--upload-pack <upload-pack>::
|
||||||
|
When given, and the repository to fetch from is handled
|
||||||
|
by 'git-fetch-pack', '--exec=<upload-pack>' is passed to
|
||||||
|
the command to specify non-default path for the command
|
||||||
|
run on the other end.
|
||||||
|
|
||||||
-f, \--force::
|
-f, \--force::
|
||||||
When `git-fetch` is used with `<rbranch>:<lbranch>`
|
When `git-fetch` is used with `<rbranch>:<lbranch>`
|
||||||
refspec, it refuses to update the local branch
|
refspec, it refuses to update the local branch
|
||||||
@ -10,15 +16,26 @@
|
|||||||
fetches is a descendant of `<lbranch>`. This option
|
fetches is a descendant of `<lbranch>`. This option
|
||||||
overrides that check.
|
overrides that check.
|
||||||
|
|
||||||
|
\--no-tags::
|
||||||
|
By default, `git-fetch` fetches tags that point at
|
||||||
|
objects that are downloaded from the remote repository
|
||||||
|
and stores them locally. This option disables this
|
||||||
|
automatic tag following.
|
||||||
|
|
||||||
-t, \--tags::
|
-t, \--tags::
|
||||||
By default, the git core utilities will not fetch and store
|
Most of the tags are fetched automatically as branch
|
||||||
tags under the same name as the remote repository; ask it
|
heads are downloaded, but tags that do not point at
|
||||||
to do so using `--tags`. Using this option will bound the
|
objects reachable from the branch heads that are being
|
||||||
list of objects pulled to the remote tags. Commits in branches
|
tracked will not be fetched by this mechanism. This
|
||||||
beyond the tags will be ignored.
|
flag lets all tags and their associated objects be
|
||||||
|
downloaded.
|
||||||
|
|
||||||
|
-k, \--keep::
|
||||||
|
Keep downloaded pack.
|
||||||
|
|
||||||
-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
|
||||||
corresponds to the current branch. This flag disables the
|
corresponds to the current branch. This flag disables the
|
||||||
check. Note that fetching into the current branch will not
|
check. Note that fetching into the current branch will not
|
||||||
update the index and working directory, so use it with care.
|
update the index and working directory, so use it with care.
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ DISCUSSION
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
The list of <file> given to the command is fed to `git-ls-files`
|
The list of <file> given to the command is fed to `git-ls-files`
|
||||||
command to list files that are not registerd in the index and
|
command to list files that are not registered in the index and
|
||||||
are not ignored/excluded by `$GIT_DIR/info/exclude` file or
|
are not ignored/excluded by `$GIT_DIR/info/exclude` file or
|
||||||
`.gitignore` file in each directory. This means two things:
|
`.gitignore` file in each directory. This means two things:
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ git-am - Apply a series of patches in a mailbox
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
|
[verse]
|
||||||
'git-am' [--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way] <mbox>...
|
'git-am' [--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way] <mbox>...
|
||||||
'git-am' [--skip | --resolved]
|
'git-am' [--skip | --resolved]
|
||||||
|
|
||||||
|
@ -8,7 +8,10 @@ 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] [--allow-binary-replacement] [-z] [<patch>...]
|
[verse]
|
||||||
|
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply]
|
||||||
|
[--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM]
|
||||||
|
[<patch>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -65,6 +68,10 @@ OPTIONS
|
|||||||
backslash characters replaced with `\t`, `\n`, and `\\`,
|
backslash characters replaced with `\t`, `\n`, and `\\`,
|
||||||
respectively.
|
respectively.
|
||||||
|
|
||||||
|
-p<n>::
|
||||||
|
Remove <n> leading slashes from traditional diff paths. The
|
||||||
|
default is 1.
|
||||||
|
|
||||||
--apply::
|
--apply::
|
||||||
If you use any of the options marked ``Turns off
|
If you use any of the options marked ``Turns off
|
||||||
"apply"'' above, git-apply reads and outputs the
|
"apply"'' above, git-apply reads and outputs the
|
||||||
|
@ -8,15 +8,15 @@ git-archimport - Import an Arch repository into git
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
`git-archimport` [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
|
[verse]
|
||||||
[ -D depth ] [ -t tempdir ]
|
`git-archimport` [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir]
|
||||||
<archive/branch> [ <archive/branch> ]
|
<archive/branch> [ <archive/branch> ]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Imports a project from one or more Arch repositories. It will follow branches
|
Imports a project from one or more Arch repositories. It will follow branches
|
||||||
and repositories within the namespaces defined by the <archive/branch>
|
and repositories within the namespaces defined by the <archive/branch>
|
||||||
parameters suppplied. If it cannot find the remote branch a merge comes from
|
parameters supplied. If it cannot find the remote branch a merge comes from
|
||||||
it will just import it as a regular commit. If it can find it, it will mark it
|
it will just import it as a regular commit. If it can find it, it will mark it
|
||||||
as a merge whenever possible (see discussion below).
|
as a merge whenever possible (see discussion below).
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ git-branch - Create a new branch, or remove an old one.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-branch' [-d | -D] [<branchname> [start-point]]
|
'git-branch' [(-d | -D) <branchname>] | [[-f] <branchname> [<start-point>]]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -25,10 +25,13 @@ OPTIONS
|
|||||||
-D::
|
-D::
|
||||||
Delete a branch irrespective of its index status.
|
Delete a branch irrespective of its index status.
|
||||||
|
|
||||||
|
-f::
|
||||||
|
Force a reset of <branchname> to <start-point> (or current head).
|
||||||
|
|
||||||
<branchname>::
|
<branchname>::
|
||||||
The name of the branch to create or delete.
|
The name of the branch to create or delete.
|
||||||
|
|
||||||
start-point::
|
<start-point>::
|
||||||
Where to create the branch; defaults to HEAD. This
|
Where to create the branch; defaults to HEAD. This
|
||||||
option has no meaning with -d and -D.
|
option has no meaning with -d and -D.
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ git-cat-file - Provide content or type information for repository objects
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-cat-file' (-t | -s | -e | <type>) <object>
|
'git-cat-file' [-t | -s | -e | <type>] <object>
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -8,6 +8,7 @@ git-checkout-index - Copy files from the index to the working directory
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
|
[verse]
|
||||||
'git-checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
|
'git-checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
|
||||||
[--stage=<number>] [--] <file>...
|
[--stage=<number>] [--] <file>...
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ git-checkout - Checkout and switch to a branch.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-checkout' [-f] [-b <new_branch>] [<branch>] [<paths>...]
|
'git-checkout' [-f] [-b <new_branch>] [-m] [<branch>] [<paths>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -34,6 +34,19 @@ OPTIONS
|
|||||||
-b::
|
-b::
|
||||||
Create a new branch and start it at <branch>.
|
Create a new branch and start it at <branch>.
|
||||||
|
|
||||||
|
-m::
|
||||||
|
If you have local modifications to a file that is
|
||||||
|
different between the current branch and the branch you
|
||||||
|
are switching to, the command refuses to switch
|
||||||
|
branches, to preserve your modifications in context.
|
||||||
|
With this option, a three-way merge between the current
|
||||||
|
branch, your working tree contents, and the new branch
|
||||||
|
is done, and you will be on the new branch.
|
||||||
|
+
|
||||||
|
When a merge conflict happens, the index entries for conflicting
|
||||||
|
paths are left unmerged, and you need to resolve the conflicts
|
||||||
|
and mark the resolved paths with `git update-index`.
|
||||||
|
|
||||||
<new_branch>::
|
<new_branch>::
|
||||||
Name for the new branch.
|
Name for the new branch.
|
||||||
|
|
||||||
@ -42,13 +55,13 @@ OPTIONS
|
|||||||
commit. Defaults to HEAD.
|
commit. Defaults to HEAD.
|
||||||
|
|
||||||
|
|
||||||
EXAMPLE
|
EXAMPLES
|
||||||
-------
|
--------
|
||||||
|
|
||||||
The following sequence checks out the `master` branch, reverts
|
. The following sequence checks out the `master` branch, reverts
|
||||||
the `Makefile` to two revisions back, deletes hello.c by
|
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 <1>
|
$ git checkout master <1>
|
||||||
$ git checkout master~2 Makefile <2>
|
$ git checkout master~2 Makefile <2>
|
||||||
@ -59,15 +72,64 @@ $ git checkout hello.c <3>
|
|||||||
<2> take out a file out of other commit
|
<2> take out a file out of other commit
|
||||||
<3> or "git checkout -- hello.c", as in the next example.
|
<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
|
||||||
last step above would be confused as an instruction to switch to
|
last step above would be confused as an instruction to switch to
|
||||||
that branch. You should instead write:
|
that branch. You should instead write:
|
||||||
|
+
|
||||||
------------
|
------------
|
||||||
$ git checkout -- hello.c
|
$ git checkout -- hello.c
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
. After working in a wrong branch, switching to the correct
|
||||||
|
branch you would want to is done with:
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git checkout mytopic
|
||||||
|
------------
|
||||||
|
+
|
||||||
|
However, your "wrong" branch and correct "mytopic" branch may
|
||||||
|
differ in files that you have locally modified, in which case,
|
||||||
|
the above checkout would fail like this:
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git checkout mytopic
|
||||||
|
fatal: Entry 'frotz' not uptodate. Cannot merge.
|
||||||
|
------------
|
||||||
|
+
|
||||||
|
You can give the `-m` flag to the command, which would try a
|
||||||
|
three-way merge:
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git checkout -m mytopic
|
||||||
|
Auto-merging frotz
|
||||||
|
------------
|
||||||
|
+
|
||||||
|
After this three-way merge, the local modifications are _not_
|
||||||
|
registered in your index file, so `git diff` would show you what
|
||||||
|
changes you made since the tip of the new branch.
|
||||||
|
|
||||||
|
. When a merge conflict happens during switching branches with
|
||||||
|
the `-m` option, you would see something like this:
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git checkout -m mytopic
|
||||||
|
Auto-merging frotz
|
||||||
|
merge: warning: conflicts during merge
|
||||||
|
ERROR: Merge conflict in frotz
|
||||||
|
fatal: merge program failed
|
||||||
|
------------
|
||||||
|
+
|
||||||
|
At this point, `git diff` shows the changes cleanly merged as in
|
||||||
|
the previous example, as well as the changes in the conflicted
|
||||||
|
files. Edit and resolve the conflict and mark it resolved with
|
||||||
|
`git update-index` as usual:
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ edit frotz
|
||||||
|
$ git update-index frotz
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -8,7 +8,9 @@ git-clone - Clones a repository.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-clone' [-l [-s]] [-q] [-n] [-u <upload-pack>] <repository> [<directory>]
|
[verse]
|
||||||
|
'git-clone' [-l [-s]] [-q] [-n] [--bare] [-o <name>] [-u <upload-pack>]
|
||||||
|
<repository> [<directory>]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -56,6 +58,21 @@ OPTIONS
|
|||||||
-n::
|
-n::
|
||||||
No checkout of HEAD is performed after the clone is complete.
|
No checkout of HEAD is performed after the clone is complete.
|
||||||
|
|
||||||
|
--bare::
|
||||||
|
Make a 'bare' GIT repository. That is, instead of
|
||||||
|
creating `<directory>` and placing the administrative
|
||||||
|
files in `<directory>/.git`, make the `<directory>`
|
||||||
|
itself the `$GIT_DIR`. This implies `-n` option. When
|
||||||
|
this option is used, neither the `origin` branch nor the
|
||||||
|
default `remotes/origin` file is created.
|
||||||
|
|
||||||
|
-o <name>::
|
||||||
|
Instead of using the branch name 'origin' to keep track
|
||||||
|
of the upstream repository, use <name> instead. Note
|
||||||
|
that the shorthand name stored in `remotes/origin` is
|
||||||
|
not affected, but the local branch name to pull the
|
||||||
|
remote `master` branch into is.
|
||||||
|
|
||||||
--upload-pack <upload-pack>::
|
--upload-pack <upload-pack>::
|
||||||
-u <upload-pack>::
|
-u <upload-pack>::
|
||||||
When given, and the repository to clone from is handled
|
When given, and the repository to clone from is handled
|
||||||
@ -94,6 +111,22 @@ $ cd copy
|
|||||||
$ git show-branch
|
$ git show-branch
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Create a bare repository to publish your changes to the public::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git clone --bare -l /home/proj/.git /pub/scm/proj.git
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Create a repository on the kernel.org machine that borrows from Linus::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git clone --bare -l -s /pub/scm/.../torvalds/linux-2.6.git \
|
||||||
|
/pub/scm/.../me/subsys-2.6.git
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org>
|
Written by Linus Torvalds <torvalds@osdl.org>
|
||||||
|
@ -60,7 +60,8 @@ either `.git/config` file, or using the following environment variables.
|
|||||||
|
|
||||||
(nb "<", ">" and "\n"s are stripped)
|
(nb "<", ">" and "\n"s are stripped)
|
||||||
|
|
||||||
In `.git/config` file, the following items are used:
|
In `.git/config` file, the following items are used for GIT_AUTHOR_NAME and
|
||||||
|
GIT_AUTHOR_EMAIL:
|
||||||
|
|
||||||
[user]
|
[user]
|
||||||
name = "Your Name"
|
name = "Your Name"
|
||||||
|
@ -7,7 +7,9 @@ git-commit - Record your changes
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg>] [-e] [--] <file>...
|
[verse]
|
||||||
|
'git-commit' [-a] [-i] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg>]
|
||||||
|
[-e] [--author <author>] [--] <file>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -23,7 +25,9 @@ information.
|
|||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
-a|--all::
|
-a|--all::
|
||||||
Update all paths in the index file.
|
Update all paths in the index file. This flag notices
|
||||||
|
files that have been modified and deleted, but new files
|
||||||
|
you have not told git about are not affected.
|
||||||
|
|
||||||
-c or -C <commit>::
|
-c or -C <commit>::
|
||||||
Take existing commit object, and reuse the log message
|
Take existing commit object, and reuse the log message
|
||||||
@ -36,6 +40,10 @@ OPTIONS
|
|||||||
Take the commit message from the given file. Use '-' to
|
Take the commit message from the given file. Use '-' to
|
||||||
read the message from the standard input.
|
read the message from the standard input.
|
||||||
|
|
||||||
|
--author <author>::
|
||||||
|
Override the author name used in the commit. Use
|
||||||
|
`A U Thor <author@example.com>` format.
|
||||||
|
|
||||||
-m <msg>::
|
-m <msg>::
|
||||||
Use the given <msg> as the commit message.
|
Use the given <msg> as the commit message.
|
||||||
|
|
||||||
@ -59,17 +67,66 @@ OPTIONS
|
|||||||
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.
|
||||||
|
|
||||||
|
-i|--include::
|
||||||
|
Instead of committing only the files specified on the
|
||||||
|
command line, update them in the index file and then
|
||||||
|
commit the whole index. This is the traditional
|
||||||
|
behaviour.
|
||||||
|
|
||||||
--::
|
--::
|
||||||
Do not interpret any more arguments as options.
|
Do not interpret any more arguments as options.
|
||||||
|
|
||||||
<file>...::
|
<file>...::
|
||||||
Update specified paths in the index file before committing.
|
Commit only the files specified on the command line.
|
||||||
|
This format cannot be used during a merge, nor when the
|
||||||
|
index and the latest commit does not match on the
|
||||||
|
specified paths to avoid confusion.
|
||||||
|
|
||||||
If you make a commit and then found a mistake immediately after
|
If you make a commit and then found a mistake immediately after
|
||||||
that, you can recover from it with gitlink:git-reset[1].
|
that, you can recover from it with gitlink:git-reset[1].
|
||||||
|
|
||||||
|
|
||||||
|
Discussion
|
||||||
|
----------
|
||||||
|
|
||||||
|
`git commit` without _any_ parameter commits the tree structure
|
||||||
|
recorded by the current index file. This is a whole-tree commit
|
||||||
|
even the command is invoked from a subdirectory.
|
||||||
|
|
||||||
|
`git commit --include paths...` is equivalent to
|
||||||
|
|
||||||
|
git update-index --remove paths...
|
||||||
|
git commit
|
||||||
|
|
||||||
|
That is, update the specified paths to the index and then commit
|
||||||
|
the whole tree.
|
||||||
|
|
||||||
|
`git commit paths...` largely bypasses the index file and
|
||||||
|
commits only the changes made to the specified paths. It has
|
||||||
|
however several safety valves to prevent confusion.
|
||||||
|
|
||||||
|
. It refuses to run during a merge (i.e. when
|
||||||
|
`$GIT_DIR/MERGE_HEAD` exists), and reminds trained git users
|
||||||
|
that the traditional semantics now needs -i flag.
|
||||||
|
|
||||||
|
. It refuses to run if named `paths...` are different in HEAD
|
||||||
|
and the index (ditto about reminding). Added paths are OK.
|
||||||
|
This is because an earlier `git diff` (not `git diff HEAD`)
|
||||||
|
would have shown the differences since the last `git
|
||||||
|
update-index paths...` to the user, and an inexperienced user
|
||||||
|
may mistakenly think that the changes between the index and
|
||||||
|
the HEAD (i.e. earlier changes made before the last `git
|
||||||
|
update-index paths...` was done) are not being committed.
|
||||||
|
|
||||||
|
. It reads HEAD commit into a temporary index file, updates the
|
||||||
|
specified `paths...` and makes a commit. At the same time,
|
||||||
|
the real index file is also updated with the same `paths...`.
|
||||||
|
|
||||||
|
`git commit --all` updates the index file with _all_ changes to
|
||||||
|
the working tree, and makes a whole-tree commit, regardless of
|
||||||
|
which subdirectory the command is invoked in.
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||||
|
@ -8,8 +8,7 @@ git-cvsexportcommit - Export a commit to a CVS checkout
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
git-cvsexportcommmit.perl
|
'git-cvsexportcommmit' [-h] [-v] [-c] [-p] [PARENTCOMMIT] COMMITID
|
||||||
[ -h ] [ -v ] [ -c ] [ -p ] [PARENTCOMMIT] COMMITID
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -18,6 +17,7 @@ Exports a commit from GIT to a CVS checkout, making it easier
|
|||||||
to merge patches from a git repository into a CVS repository.
|
to merge patches from a git repository into a CVS repository.
|
||||||
|
|
||||||
Execute it from the root of the CVS working copy. GIT_DIR must be defined.
|
Execute it from the root of the CVS working copy. GIT_DIR must be defined.
|
||||||
|
See examples below.
|
||||||
|
|
||||||
It does its best to do the safe thing, it will check that the files are
|
It does its best to do the safe thing, it will check that the files are
|
||||||
unchanged and up to date in the CVS checkout, and it will not autocommit
|
unchanged and up to date in the CVS checkout, and it will not autocommit
|
||||||
@ -42,6 +42,26 @@ OPTIONS
|
|||||||
-v::
|
-v::
|
||||||
Verbose.
|
Verbose.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
|
||||||
|
Merge one patch into CVS::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ export GIT_DIR=~/project/.git
|
||||||
|
$ cd ~/project_cvs_checkout
|
||||||
|
$ git-cvsexportcommit -v <commit-sha1>
|
||||||
|
$ cvs commit -F .mgs <files>
|
||||||
|
------------
|
||||||
|
|
||||||
|
Merge pending patches into CVS automatically -- only if you really know what you are doing ::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ export GIT_DIR=~/project/.git
|
||||||
|
$ cd ~/project_cvs_checkout
|
||||||
|
$ git-cherry cvshead myhead | sed -n 's/^+ //p' | xargs -l1 git-cvsexportcommit -c -p -v
|
||||||
|
------------
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Martin Langhoff <martin@catalyst.net.nz>
|
Written by Martin Langhoff <martin@catalyst.net.nz>
|
||||||
|
@ -8,10 +8,10 @@ git-cvsimport - Import a CVS repository into git
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-cvsimport' [ -o <branch-for-HEAD> ] [ -h ] [ -v ]
|
[verse]
|
||||||
[ -d <CVSROOT> ] [ -p <options-for-cvsps> ]
|
'git-cvsimport' [-o <branch-for-HEAD>] [-h] [-v] [-d <CVSROOT>] [-s <subst>]
|
||||||
[ -C <git_repository> ] [ -i ] [ -P <file> ] [ -k ]
|
[-p <options-for-cvsps>] [-C <git_repository>] [-i] [-P <file>]
|
||||||
[ -s <subst> ] [ -m ] [ -M regex ] [ <CVS_module> ]
|
[-m] [-M regex] [<CVS_module>]
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -89,6 +89,26 @@ If you need to pass multiple options, separate them with a comma.
|
|||||||
-s <subst>::
|
-s <subst>::
|
||||||
Substitute the character "/" in branch names with <subst>
|
Substitute the character "/" in branch names with <subst>
|
||||||
|
|
||||||
|
-A <author-conv-file>::
|
||||||
|
CVS by default uses the unix username when writing its
|
||||||
|
commit logs. Using this option and an author-conv-file
|
||||||
|
in this format
|
||||||
|
|
||||||
|
exon=Andreas Ericsson <ae@op5.se>
|
||||||
|
spawn=Simon Pawn <spawn@frog-pond.org>
|
||||||
|
|
||||||
|
git-cvsimport will make it appear as those authors had
|
||||||
|
their GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL set properly
|
||||||
|
all along.
|
||||||
|
|
||||||
|
For convenience, this data is saved to $GIT_DIR/cvs-authors
|
||||||
|
each time the -A option is provided and read from that same
|
||||||
|
file each time git-cvsimport is run.
|
||||||
|
|
||||||
|
It is not recommended to use this feature if you intend to
|
||||||
|
export changes back to CVS again later with
|
||||||
|
git-link[1]::git-cvsexportcommit.
|
||||||
|
|
||||||
OUTPUT
|
OUTPUT
|
||||||
------
|
------
|
||||||
If '-v' is specified, the script reports what it is doing.
|
If '-v' is specified, the script reports what it is doing.
|
||||||
|
@ -7,8 +7,11 @@ git-daemon - A really simple server for git repositories.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
|
[verse]
|
||||||
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
|
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
|
||||||
[--timeout=n] [--init-timeout=n] [--strict-paths] [directory...]
|
[--timeout=n] [--init-timeout=n] [--strict-paths]
|
||||||
|
[--base-path=path] [--user-path | --user-path=path]
|
||||||
|
[directory...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -35,6 +38,13 @@ OPTIONS
|
|||||||
git-daemon will refuse to start when this option is enabled and no
|
git-daemon will refuse to start when this option is enabled and no
|
||||||
whitelist is specified.
|
whitelist is specified.
|
||||||
|
|
||||||
|
--base-path::
|
||||||
|
Remap all the path requests as relative to the given path.
|
||||||
|
This is sort of "GIT root" - if you run git-daemon with
|
||||||
|
'--base-path=/srv/git' on example.com, then if you later try to pull
|
||||||
|
'git://example.com/hello.git', `git-daemon` will interpret the path
|
||||||
|
as '/srv/git/hello.git'.
|
||||||
|
|
||||||
--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' and 'refs' subdirectories), even if they
|
(have the 'objects' and 'refs' subdirectories), even if they
|
||||||
@ -60,6 +70,15 @@ OPTIONS
|
|||||||
Log to syslog instead of stderr. Note that this option does not imply
|
Log to syslog instead of stderr. Note that this option does not imply
|
||||||
--verbose, thus by default only error conditions will be logged.
|
--verbose, thus by default only error conditions will be logged.
|
||||||
|
|
||||||
|
--user-path, --user-path=path::
|
||||||
|
Allow ~user notation to be used in requests. When
|
||||||
|
specified with no parameter, requests to
|
||||||
|
git://host/~alice/foo is taken as a request to access
|
||||||
|
'foo' repository in the home directory of user `alice`.
|
||||||
|
If `--user-path=path` is specified, the same request is
|
||||||
|
taken as a request to access `path/foo` repository in
|
||||||
|
the home directory of user `alice`.
|
||||||
|
|
||||||
--verbose::
|
--verbose::
|
||||||
Log details about the incoming connections and requested files.
|
Log details about the incoming connections and requested files.
|
||||||
|
|
||||||
|
79
Documentation/git-describe.txt
Normal file
79
Documentation/git-describe.txt
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
git-describe(1)
|
||||||
|
===============
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
git-describe - Show the most recent tag that is reachable from a commit.
|
||||||
|
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
--------
|
||||||
|
'git-describe' [--all] [--tags] [--abbrev=<n>] <committish>...
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
The command finds the most recent tag that is reachable from a
|
||||||
|
commit, and if the commit itself is pointed at by the tag, shows
|
||||||
|
the tag. Otherwise, it suffixes the tag name with abbreviated
|
||||||
|
object name of the commit.
|
||||||
|
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
<committish>::
|
||||||
|
The object name of the comittish.
|
||||||
|
|
||||||
|
--all::
|
||||||
|
Instead of using only the annotated tags, use any ref
|
||||||
|
found in `.git/refs/`.
|
||||||
|
|
||||||
|
--tags::
|
||||||
|
Instead of using only the annotated tags, use any tag
|
||||||
|
found in `.git/refs/tags`.
|
||||||
|
|
||||||
|
--abbrev=<n>::
|
||||||
|
Instead of using the default 8 hexadecimal digits as the
|
||||||
|
abbreviated object name, use <n> digits.
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
|
||||||
|
With something like git.git current tree, I get:
|
||||||
|
|
||||||
|
[torvalds@g5 git]$ git-describe parent
|
||||||
|
v1.0.4-g2414721b
|
||||||
|
|
||||||
|
i.e. the current head of my "parent" branch is based on v1.0.4,
|
||||||
|
but since it has a few commits on top of that, it has added the
|
||||||
|
git hash of the thing to the end: "-g" + 8-char shorthand for
|
||||||
|
the commit `2414721b194453f058079d897d13c4e377f92dc6`.
|
||||||
|
|
||||||
|
Doing a "git-describe" on a tag-name will just show the tag name:
|
||||||
|
|
||||||
|
[torvalds@g5 git]$ git-describe v1.0.4
|
||||||
|
v1.0.4
|
||||||
|
|
||||||
|
With --all, the command can use branch heads as references, so
|
||||||
|
the output shows the reference path as well:
|
||||||
|
|
||||||
|
[torvalds@g5 git]$ git describe --all --abbrev=4 v1.0.5^2
|
||||||
|
tags/v1.0.0-g975b
|
||||||
|
|
||||||
|
[torvalds@g5 git]$ git describe --all HEAD^
|
||||||
|
heads/lt/describe-g975b
|
||||||
|
|
||||||
|
|
||||||
|
Author
|
||||||
|
------
|
||||||
|
Written by Linus Torvalds <torvalds@osdl.org>, but somewhat
|
||||||
|
butchered by Junio C Hamano <junkio@cox.net>
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
--------------
|
||||||
|
Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
|
||||||
|
|
||||||
|
GIT
|
||||||
|
---
|
||||||
|
Part of the gitlink:git[7] suite
|
||||||
|
|
@ -8,7 +8,7 @@ git-diff-files - Compares files in the working tree and the index
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-diff-files' [-q] [<common diff options>] [<path>...]
|
'git-diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -30,6 +30,12 @@ The default is to diff against our branch (-2) and the
|
|||||||
cleanly resolved paths. The option -0 can be given to
|
cleanly resolved paths. The option -0 can be given to
|
||||||
omit diff output for unmerged entries and just show "Unmerged".
|
omit diff output for unmerged entries and just show "Unmerged".
|
||||||
|
|
||||||
|
-c,--cc::
|
||||||
|
This compares stage 2 (our branch), stage 3 (their
|
||||||
|
branch) and the working tree file and outputs a combined
|
||||||
|
diff, similar to the way 'diff-tree' shows a merge
|
||||||
|
commit with these flags.
|
||||||
|
|
||||||
-q::
|
-q::
|
||||||
Remain silent even on nonexisting files
|
Remain silent even on nonexisting files
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ If '--cached' is specified, it allows you to ask:
|
|||||||
contents (the ones I'd write with a "git-write-tree")
|
contents (the ones I'd write with a "git-write-tree")
|
||||||
|
|
||||||
For example, let's say that you have worked on your working directory, updated
|
For example, let's say that you have worked on your working directory, updated
|
||||||
some files in the index and are ready to commit. You want to see eactly
|
some files in the index and are ready to commit. You want to see exactly
|
||||||
*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
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ NOTE: As with other commands of this type, "git-diff-index" does not
|
|||||||
actually look at the contents of the file at all. So maybe
|
actually look at the contents of the file at all. So maybe
|
||||||
`kernel/sched.c` hasn't actually changed, and it's just that you
|
`kernel/sched.c` hasn't actually changed, and it's just that you
|
||||||
touched it. In either case, it's a note that you need to
|
touched it. In either case, it's a note that you need to
|
||||||
"git-upate-index" it to make the index be in sync.
|
"git-update-index" it to make the index be in sync.
|
||||||
|
|
||||||
NOTE: You can have a mixture of files show up as "has been updated"
|
NOTE: You can have a mixture of files show up as "has been updated"
|
||||||
and "is still dirty in the working directory" together. You can always
|
and "is still dirty in the working directory" together. You can always
|
||||||
|
@ -8,7 +8,10 @@ git-diff-tree - Compares the content and mode of blobs found via two tree object
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-diff-tree' [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty] [-t] [-r] [--root] [<common diff options>] <tree-ish> [<tree-ish>] [<path>...]
|
[verse]
|
||||||
|
'git-diff-tree' [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]
|
||||||
|
[-t] [-r] [-c | --cc] [--root] [<common diff options>]
|
||||||
|
<tree-ish> [<tree-ish>] [<path>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -62,7 +65,7 @@ separated with a single space are given.
|
|||||||
-s::
|
-s::
|
||||||
By default, "git-diff-tree --stdin" shows differences,
|
By default, "git-diff-tree --stdin" shows differences,
|
||||||
either in machine-readable form (without '-p') or in patch
|
either in machine-readable form (without '-p') or in patch
|
||||||
form (with '-p'). This output can be supressed. It is
|
form (with '-p'). This output can be suppressed. It is
|
||||||
only useful with '-v' flag.
|
only useful with '-v' flag.
|
||||||
|
|
||||||
-v::
|
-v::
|
||||||
@ -78,6 +81,24 @@ separated with a single space are given.
|
|||||||
git-diff-tree outputs a line with the commit ID when
|
git-diff-tree outputs a line with the commit ID when
|
||||||
applicable. This flag suppressed the commit ID output.
|
applicable. This flag suppressed the commit ID output.
|
||||||
|
|
||||||
|
-c,--cc::
|
||||||
|
These flags change the way a merge commit is displayed
|
||||||
|
(which means it is useful only when the command is given
|
||||||
|
one <tree-ish>, or '--stdin'). It shows the differences
|
||||||
|
from each of the parents to the merge result
|
||||||
|
simultaneously, instead of showing pairwise diff between
|
||||||
|
a parent and the result one at a time, which '-m' option
|
||||||
|
output does. '--cc' further compresses the output by
|
||||||
|
omiting hunks that show differences from only one
|
||||||
|
parent, or show the same change from all but one parent
|
||||||
|
for an Octopus merge. When this optimization makes all
|
||||||
|
hunks disappear, the commit itself and the commit log
|
||||||
|
message is not shown, just like any other "empty diff" cases.
|
||||||
|
|
||||||
|
--always::
|
||||||
|
Show the commit itself and the commit log message even
|
||||||
|
if the diff itself is empty.
|
||||||
|
|
||||||
|
|
||||||
Limiting Output
|
Limiting Output
|
||||||
---------------
|
---------------
|
||||||
|
@ -67,7 +67,7 @@ $ git diff HEAD^ HEAD <3>
|
|||||||
<1> instead of using the tip of the current branch, compare with the
|
<1> instead of using the tip of the current branch, compare with the
|
||||||
tip of "test" branch.
|
tip of "test" branch.
|
||||||
<2> instead of comparing with the tip of "test" branch, compare with
|
<2> instead of comparing with the tip of "test" branch, compare with
|
||||||
the tip of the curren branch, but limit the comparison to the
|
the tip of the current branch, but limit the comparison to the
|
||||||
file "test".
|
file "test".
|
||||||
<3> compare the version before the last commit and the last commit.
|
<3> compare the version before the last commit and the last commit.
|
||||||
------------
|
------------
|
||||||
|
@ -27,7 +27,7 @@ include::fetch-options.txt[]
|
|||||||
|
|
||||||
include::pull-fetch-param.txt[]
|
include::pull-fetch-param.txt[]
|
||||||
|
|
||||||
|
include::urls.txt[]
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
|
@ -8,27 +8,28 @@ git-format-patch - Prepare patches for e-mail submission.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-format-patch' [-n | -k] [-o <dir> | --stdout] [-s] [-c] [--mbox] [--diff-options] <his> [<mine>]
|
[verse]
|
||||||
|
'git-format-patch' [-n | -k] [-o <dir> | --stdout] [-s] [-c]
|
||||||
|
[--diff-options] <his> [<mine>]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Prepare each commit with its patch since <mine> head forked from
|
Prepare each commit with its patch since <mine> head forked from
|
||||||
<his> head, one file per patch, for e-mail submission. Each
|
<his> head, one file per patch formatted to resemble UNIX mailbox
|
||||||
output file is numbered sequentially from 1, and uses the first
|
format, for e-mail submission or use with gitlink:git-am[1].
|
||||||
line of the commit message (massaged for pathname safety) as the
|
|
||||||
filename.
|
|
||||||
|
|
||||||
When -o is specified, output files are created in that
|
Each output file is numbered sequentially from 1, and uses the
|
||||||
directory; otherwise in the current working directory.
|
first line of the commit message (massaged for pathname safety)
|
||||||
|
as the filename.
|
||||||
|
|
||||||
|
When -o is specified, output files are created in <dir>; otherwise
|
||||||
|
they are created in the current working directory. This option
|
||||||
|
is ignored if --stdout is specified.
|
||||||
|
|
||||||
When -n is specified, instead of "[PATCH] Subject", the first
|
When -n is specified, instead of "[PATCH] Subject", the first
|
||||||
line is formatted as "[PATCH N/M] Subject", unless you have only
|
line is formatted as "[PATCH N/M] Subject", unless you have only
|
||||||
one patch.
|
one patch.
|
||||||
|
|
||||||
When --mbox is specified, the output is formatted to resemble
|
|
||||||
UNIX mailbox format, and can be concatenated together for
|
|
||||||
processing with applymbox.
|
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
@ -43,11 +44,6 @@ OPTIONS
|
|||||||
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.
|
||||||
|
|
||||||
-a|--author, -d|--date::
|
|
||||||
Output From: and Date: headers for commits made by
|
|
||||||
yourself as well. Usually these are output only for
|
|
||||||
commits made by people other than yourself.
|
|
||||||
|
|
||||||
-s|--signoff::
|
-s|--signoff::
|
||||||
Add `Signed-off-by:` line to the commit message, using
|
Add `Signed-off-by:` line to the commit message, using
|
||||||
the committer identity of yourself.
|
the committer identity of yourself.
|
||||||
@ -59,12 +55,6 @@ OPTIONS
|
|||||||
has a SP character immediately followed by a TAB
|
has a SP character immediately followed by a TAB
|
||||||
character.
|
character.
|
||||||
|
|
||||||
-m|--mbox::
|
|
||||||
Format the output files for closer to mbox format by
|
|
||||||
adding a phony Unix "From " line, so they can be
|
|
||||||
concatenated together and fed to `git-applymbox`.
|
|
||||||
Implies --author and --date.
|
|
||||||
|
|
||||||
--stdout::
|
--stdout::
|
||||||
This flag generates the mbox formatted output to the
|
This flag generates the mbox formatted output to the
|
||||||
standard output, instead of saving them into a file per
|
standard output, instead of saving them into a file per
|
||||||
@ -96,7 +86,7 @@ git-format-patch -M -B origin::
|
|||||||
|
|
||||||
See Also
|
See Also
|
||||||
--------
|
--------
|
||||||
gitlink:git-am[1], gitlink:git-send-email
|
gitlink:git-am[1], gitlink:git-send-email[1]
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
|
@ -8,7 +8,9 @@ git-fsck-objects - Verifies the connectivity and validity of the objects in the
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-fsck-objects' [--tags] [--root] [--unreachable] [--cache] [--standalone | --full] [--strict] [<object>*]
|
[verse]
|
||||||
|
'git-fsck-objects' [--tags] [--root] [--unreachable] [--cache]
|
||||||
|
[--standalone | --full] [--strict] [<object>*]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -8,7 +8,7 @@ git-grep - print lines matching a pattern
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-grep' <option>... <pattern> <path>...
|
'git-grep' [<option>...] [-e] <pattern> [--] [<path>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -18,16 +18,26 @@ containing a match to the given pattern.
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
`--`::
|
||||||
|
Signals the end of options; the rest of the parameters
|
||||||
|
are <path> limiters.
|
||||||
|
|
||||||
<option>...::
|
<option>...::
|
||||||
Either an option to pass to `grep` or `git-ls-files`.
|
Either an option to pass to `grep` or `git-ls-files`.
|
||||||
Some `grep` options, such as `-C` and `-m`, that take
|
|
||||||
parameters are known to `git-grep`.
|
The following are the specific `git-ls-files` options
|
||||||
|
that may be given: `-o`, `--cached`, `--deleted`, `--others`,
|
||||||
|
`--killed`, `--ignored`, `--modified`, `--exclude=*`,
|
||||||
|
`--exclude-from=*`, and `--exclude-per-directory=*`.
|
||||||
|
|
||||||
|
All other options will be passed to `grep`.
|
||||||
|
|
||||||
<pattern>::
|
<pattern>::
|
||||||
The pattern to look for.
|
The pattern to look for. The first non option is taken
|
||||||
|
as the pattern; if your pattern begins with a dash, use
|
||||||
|
`-e <pattern>`.
|
||||||
|
|
||||||
<path>...::
|
<path>...::
|
||||||
|
|
||||||
Optional paths to limit the set of files to be searched;
|
Optional paths to limit the set of files to be searched;
|
||||||
passed to `git-ls-files`.
|
passed to `git-ls-files`.
|
||||||
|
|
||||||
|
@ -3,12 +3,12 @@ git-http-fetch(1)
|
|||||||
|
|
||||||
NAME
|
NAME
|
||||||
----
|
----
|
||||||
git-http-fetch - Downloads a remote git repository via HTTP
|
git-http-fetch - downloads a remote git repository via HTTP
|
||||||
|
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] commit-id url
|
'git-http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] <commit> <url>
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -8,7 +8,7 @@ git-init-db - Creates an empty git repository
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-init-db' [--template=<template_directory>]
|
'git-init-db' [--template=<template_directory>] [--shared]
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
@ -16,6 +16,9 @@ OPTIONS
|
|||||||
--template=<template_directory>::
|
--template=<template_directory>::
|
||||||
Provide the directory in from which templates will be used.
|
Provide the directory in from which templates will be used.
|
||||||
|
|
||||||
|
--shared::
|
||||||
|
Specify that the git repository is to be shared amongst several users.
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -30,7 +33,16 @@ 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.
|
A shared repository allows users belonging to the same group to push into that
|
||||||
|
repository. When specifying `--shared` the config variable "core.sharedRepository"
|
||||||
|
is set to 'true' so that directories under `$GIT_DIR` are made group writable
|
||||||
|
(and g+sx, since the git group may be not the primary group of all users).
|
||||||
|
|
||||||
|
|
||||||
|
Running `git-init-db` in an existing repository is safe. It will not overwrite
|
||||||
|
things that are already there. The primary reason for rerunning `git-init-db`
|
||||||
|
is to pick up newly added templates.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
|
@ -13,7 +13,8 @@ SYNOPSIS
|
|||||||
(-[c|d|o|i|s|u|k|m])\*
|
(-[c|d|o|i|s|u|k|m])\*
|
||||||
[-x <pattern>|--exclude=<pattern>]
|
[-x <pattern>|--exclude=<pattern>]
|
||||||
[-X <file>|--exclude-from=<file>]
|
[-X <file>|--exclude-from=<file>]
|
||||||
[--exclude-per-directory=<file>] [--] [<file>]\*
|
[--exclude-per-directory=<file>]
|
||||||
|
[--full-name] [--] [<file>]\*
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -45,6 +46,10 @@ OPTIONS
|
|||||||
-s|--stage::
|
-s|--stage::
|
||||||
Show stage files in the output
|
Show stage files in the output
|
||||||
|
|
||||||
|
--directory::
|
||||||
|
If a whole directory is classified as "other", show just its
|
||||||
|
name (with a trailing slash) and not its whole contents.
|
||||||
|
|
||||||
-u|--unmerged::
|
-u|--unmerged::
|
||||||
Show unmerged files in the output (forces --stage)
|
Show unmerged files in the output (forces --stage)
|
||||||
|
|
||||||
@ -73,10 +78,16 @@ OPTIONS
|
|||||||
H:: cached
|
H:: cached
|
||||||
M:: unmerged
|
M:: unmerged
|
||||||
R:: removed/deleted
|
R:: removed/deleted
|
||||||
C:: modifed/changed
|
C:: modified/changed
|
||||||
K:: to be killed
|
K:: to be killed
|
||||||
? other
|
? other
|
||||||
|
|
||||||
|
--full-name::
|
||||||
|
When run from a subdirectory, the command usually
|
||||||
|
outputs paths relative to the current directory. This
|
||||||
|
option forces paths to be output relative to the project
|
||||||
|
top directory.
|
||||||
|
|
||||||
--::
|
--::
|
||||||
Do not interpret any more arguments as options.
|
Do not interpret any more arguments as options.
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ base-name::
|
|||||||
output of the command.
|
output of the command.
|
||||||
|
|
||||||
--stdout::
|
--stdout::
|
||||||
Write the pack contents (what would have been writtin to
|
Write the pack contents (what would have been written to
|
||||||
.pack file) out to the standard output.
|
.pack file) out to the standard output.
|
||||||
|
|
||||||
--window and --depth::
|
--window and --depth::
|
||||||
|
@ -29,8 +29,9 @@ include::fetch-options.txt[]
|
|||||||
|
|
||||||
include::pull-fetch-param.txt[]
|
include::pull-fetch-param.txt[]
|
||||||
|
|
||||||
include::merge-strategies.txt[]
|
include::urls.txt[]
|
||||||
|
|
||||||
|
include::merge-strategies.txt[]
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
@ -8,7 +8,7 @@ git-push - Update remote refs along with associated objects.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-push' [--all] [--force] <repository> <refspec>...
|
'git-push' [--all] [--tags] [--force] <repository> <refspec>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -16,25 +16,56 @@ 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
|
You can make interesting things happen to a repository
|
||||||
every time you push into it, by setting up 'hooks' there. See
|
every time you push into it, by setting up 'hooks' there. See
|
||||||
documentation for gitlink:git-receive-pack[1].
|
documentation for gitlink:git-receive-pack[1].
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
include::pull-fetch-param.txt[]
|
<repository>::
|
||||||
|
The "remote" repository that is destination of a push
|
||||||
|
operation. See the section <<URLS,GIT URLS>> below.
|
||||||
|
|
||||||
|
<refspec>::
|
||||||
|
The canonical format of a <refspec> parameter is
|
||||||
|
`+?<src>:<dst>`; that is, an optional plus `+`, followed
|
||||||
|
by the source ref, followed by a colon `:`, followed by
|
||||||
|
the destination ref.
|
||||||
|
+
|
||||||
|
The <src> side can be an
|
||||||
|
arbitrary "SHA1 expression" that can be used as an
|
||||||
|
argument to `git-cat-file -t`. E.g. `master~4` (push
|
||||||
|
four parents before the current master head).
|
||||||
|
+
|
||||||
|
The local ref that matches <src> is used
|
||||||
|
to fast forward the remote ref that matches <dst>. If
|
||||||
|
the optional plus `+` is used, the remote ref is updated
|
||||||
|
even if it does not result in a fast forward update.
|
||||||
|
+
|
||||||
|
Some short-cut notations are also supported.
|
||||||
|
+
|
||||||
|
* `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
|
||||||
|
* A parameter <ref> without a colon is equivalent to
|
||||||
|
<ref>`:`<ref>, hence updates <ref> in the destination from <ref>
|
||||||
|
in the source.
|
||||||
|
|
||||||
\--all::
|
\--all::
|
||||||
Instead of naming each ref to push, specifies all refs
|
Instead of naming each ref to push, specifies that all
|
||||||
to be pushed.
|
refs be pushed.
|
||||||
|
|
||||||
|
\--tags::
|
||||||
|
All refs under `$GIT_DIR/refs/tags` are pushed, in
|
||||||
|
addition to refspecs explicitly listed on the command
|
||||||
|
line.
|
||||||
|
|
||||||
-f, \--force::
|
-f, \--force::
|
||||||
Usually, the command refuses to update a local ref that is
|
Usually, the command refuses to update a remote ref that is
|
||||||
not an ancestor of the remote ref used to overwrite it.
|
not a descendent of the local ref used to overwrite it.
|
||||||
This flag disables the check. What this means is that the
|
This flag disables the check. This can cause the
|
||||||
local repository can lose commits; use it with care.
|
remote repository to lose commits; use it with care.
|
||||||
|
|
||||||
|
include::urls.txt[]
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -8,12 +8,12 @@ git-repo-config - Get and set options in .git/config.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-repo-config' name [value [value_regex]]
|
'git-repo-config' [type] name [value [value_regex]]
|
||||||
'git-repo-config' --replace-all name [value [value_regex]]
|
'git-repo-config' [type] --replace-all name [value [value_regex]]
|
||||||
'git-repo-config' --get name [value_regex]
|
'git-repo-config' [type] --get name [value_regex]
|
||||||
'git-repo-config' --get-all name [value_regex]
|
'git-repo-config' [type] --get-all name [value_regex]
|
||||||
'git-repo-config' --unset name [value_regex]
|
'git-repo-config' [type] --unset name [value_regex]
|
||||||
'git-repo-config' --unset-all name [value_regex]
|
'git-repo-config' [type] --unset-all name [value_regex]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -21,11 +21,17 @@ 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
|
actually the section and the key separated by a dot, and the value will be
|
||||||
escaped.
|
escaped.
|
||||||
|
|
||||||
If you want to set/unset an option which can occor on multiple lines, you
|
If you want to set/unset an option which can occur on multiple lines, you
|
||||||
should provide a POSIX regex for the value. If you want to handle the lines
|
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
|
*not* matching the regex, just prepend a single exclamation mark in front
|
||||||
(see EXAMPLES).
|
(see EXAMPLES).
|
||||||
|
|
||||||
|
The type specifier can be either '--int' or '--bool', which will make
|
||||||
|
'git-repo-config' ensure that the variable(s) are of the given type and
|
||||||
|
convert the value to the canonical form (simple decimal number for int,
|
||||||
|
a "true" or "false" string for bool). If no type specifier is passed,
|
||||||
|
no checks or transformations are performed on the value.
|
||||||
|
|
||||||
This command will fail if
|
This command will fail if
|
||||||
|
|
||||||
. .git/config is invalid,
|
. .git/config is invalid,
|
||||||
|
177
Documentation/git-rerere.txt
Normal file
177
Documentation/git-rerere.txt
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
git-rerere(1)
|
||||||
|
=============
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
git-rerere - Reuse recorded resolve
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
--------
|
||||||
|
'git-rerere'
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
|
||||||
|
In a workflow that employs relatively long lived topic branches,
|
||||||
|
the developer sometimes needs to resolve the same conflict over
|
||||||
|
and over again until the topic branches are done (either merged
|
||||||
|
to the "release" branch, or sent out and accepted upstream).
|
||||||
|
|
||||||
|
This command helps this process by recording conflicted
|
||||||
|
automerge results and corresponding hand-resolve results on the
|
||||||
|
initial manual merge, and later by noticing the same automerge
|
||||||
|
results and applying the previously recorded hand resolution.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
You need to create `$GIT_DIR/rr-cache` directory to enable this
|
||||||
|
command.
|
||||||
|
|
||||||
|
DISCUSSION
|
||||||
|
----------
|
||||||
|
|
||||||
|
When your topic branch modifies overlapping area that your
|
||||||
|
master branch (or upstream) touched since your topic branch
|
||||||
|
forked from it, you may want to test it with the latest master,
|
||||||
|
even before your topic branch is ready to be pushed upstream:
|
||||||
|
|
||||||
|
------------
|
||||||
|
o---*---o topic
|
||||||
|
/
|
||||||
|
o---o---o---*---o---o master
|
||||||
|
------------
|
||||||
|
|
||||||
|
For such a test, you need to merge master and topic somehow.
|
||||||
|
One way to do it is to pull master into the topic branch:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git checkout topic
|
||||||
|
$ git pull . master
|
||||||
|
|
||||||
|
o---*---o---+ topic
|
||||||
|
/ /
|
||||||
|
o---o---o---*---o---o master
|
||||||
|
------------
|
||||||
|
|
||||||
|
The commits marked with `*` touch the same area in the same
|
||||||
|
file; you need to resolve the conflicts when creating the commit
|
||||||
|
marked with `+`. Then you can test the result to make sure your
|
||||||
|
work-in-progress still works with what is in the latest master.
|
||||||
|
|
||||||
|
After this test merge, there are two ways to continue your work
|
||||||
|
on the topic. The easiest is to build on top of the test merge
|
||||||
|
commit `+`, and when your work in the topic branch is finally
|
||||||
|
ready, pull the topic branch into master, and/or ask the
|
||||||
|
upstream to pull from you. By that time, however, the master or
|
||||||
|
the upstream might have been advanced since the test merge `+`,
|
||||||
|
in which case the final commit graph would look like this:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git checkout topic
|
||||||
|
$ git pull . master
|
||||||
|
$ ... work on both topic and master branches
|
||||||
|
$ git checkout master
|
||||||
|
$ git pull . topic
|
||||||
|
|
||||||
|
o---*---o---+---o---o topic
|
||||||
|
/ / \
|
||||||
|
o---o---o---*---o---o---o---o---+ master
|
||||||
|
------------
|
||||||
|
|
||||||
|
When your topic branch is long-lived, however, your topic branch
|
||||||
|
would end up having many such "Merge from master" commits on it,
|
||||||
|
which would unnecessarily clutter the development history.
|
||||||
|
Readers of the Linux kernel mailing list may remember that Linus
|
||||||
|
complained about such too frequent test merges when a subsystem
|
||||||
|
maintainer asked to pull from a branch full of "useless merges".
|
||||||
|
|
||||||
|
As an alternative, to keep the topic branch clean of test
|
||||||
|
merges, you could blow away the test merge, and keep building on
|
||||||
|
top of the tip before the test merge:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git checkout topic
|
||||||
|
$ git pull . master
|
||||||
|
$ git reset --hard HEAD^ ;# rewind the test merge
|
||||||
|
$ ... work on both topic and master branches
|
||||||
|
$ git checkout master
|
||||||
|
$ git pull . topic
|
||||||
|
|
||||||
|
o---*---o-------o---o topic
|
||||||
|
/ \
|
||||||
|
o---o---o---*---o---o---o---o---+ master
|
||||||
|
------------
|
||||||
|
|
||||||
|
This would leave only one merge commit when your topic branch is
|
||||||
|
finally ready and merged into the master branch. This merge
|
||||||
|
would require you to resolve the conflict, introduced by the
|
||||||
|
commits marked with `*`. However, often this conflict is the
|
||||||
|
same conflict you resolved when you created the test merge you
|
||||||
|
blew away. `git-rerere` command helps you to resolve this final
|
||||||
|
conflicted merge using the information from your earlier hand
|
||||||
|
resolve.
|
||||||
|
|
||||||
|
Running `git-rerere` command immediately after a conflicted
|
||||||
|
automerge records the conflicted working tree files, with the
|
||||||
|
usual conflict markers `<<<<<<<`, `=======`, and `>>>>>>>` in
|
||||||
|
them. Later, after you are done resolving the conflicts,
|
||||||
|
running `git-rerere` again records the resolved state of these
|
||||||
|
files. Suppose you did this when you created the test merge of
|
||||||
|
master into the topic branch.
|
||||||
|
|
||||||
|
Next time, running `git-rerere` after seeing a conflicted
|
||||||
|
automerge, if the conflict is the same as the earlier one
|
||||||
|
recorded, it is noticed and a three-way merge between the
|
||||||
|
earlier conflicted automerge, the earlier manual resolution, and
|
||||||
|
the current conflicted automerge is performed by the command.
|
||||||
|
If this three-way merge resolves cleanly, the result is written
|
||||||
|
out to your working tree file, so you would not have to manually
|
||||||
|
resolve it. Note that `git-rerere` leaves the index file alone,
|
||||||
|
so you still need to do the final sanity checks with `git diff`
|
||||||
|
(or `git diff -c`) and `git update-index` when you are
|
||||||
|
satisfied.
|
||||||
|
|
||||||
|
As a convenience measure, `git-merge` automatically invokes
|
||||||
|
`git-rerere` when it exits with a failed automerge, which
|
||||||
|
records it if it is a new conflict, or reuses the earlier hand
|
||||||
|
resolve when it is not. `git-commit` also invokes `git-rerere`
|
||||||
|
when recording a merge result. What this means is that you do
|
||||||
|
not have to do anything special yourself (Note: you still have
|
||||||
|
to create `$GIT_DIR/rr-cache` directory to enable this command).
|
||||||
|
|
||||||
|
In our example, when you did the test merge, the manual
|
||||||
|
resolution is recorded, and it will be reused when you do the
|
||||||
|
actual merge later with updated master and topic branch, as long
|
||||||
|
as the earlier resolution is still applicable.
|
||||||
|
|
||||||
|
The information `git-rerere` records is also used when running
|
||||||
|
`git-rebase`. After blowing away the test merge and continuing
|
||||||
|
development on the topic branch:
|
||||||
|
|
||||||
|
------------
|
||||||
|
o---*---o-------o---o topic
|
||||||
|
/
|
||||||
|
o---o---o---*---o---o---o---o master
|
||||||
|
|
||||||
|
$ git rebase master topic
|
||||||
|
|
||||||
|
o---*---o-------o---o topic
|
||||||
|
/
|
||||||
|
o---o---o---*---o---o---o---o master
|
||||||
|
------------
|
||||||
|
|
||||||
|
you could run `git rebase master topic`, to keep yourself
|
||||||
|
up-to-date even before your topic is ready to be sent upstream.
|
||||||
|
This would result in falling back to three-way merge, and it
|
||||||
|
would conflict the same way the test merge you resolved earlier.
|
||||||
|
`git-rerere` is run by `git rebase` to help you resolve this
|
||||||
|
conflict.
|
||||||
|
|
||||||
|
|
||||||
|
Author
|
||||||
|
------
|
||||||
|
Written by Junio C Hamano <junkio@cox.net>
|
||||||
|
|
||||||
|
GIT
|
||||||
|
---
|
||||||
|
Part of the gitlink:git[7] suite
|
@ -145,6 +145,32 @@ brings your index file and the working tree back to that state,
|
|||||||
and resets the tip of the branch to that commit.
|
and resets the tip of the branch to that commit.
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
Interrupted workflow::
|
||||||
|
+
|
||||||
|
Suppose you are interrupted by an urgent fix request while you
|
||||||
|
are in the middle of a large change. The files in your
|
||||||
|
working tree are not in any shape to be committed yet, but you
|
||||||
|
need to get to the other branch for a quick bugfix.
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git checkout feature ;# you were working in "feature" branch and
|
||||||
|
$ work work work ;# got interrupted
|
||||||
|
$ git commit -a -m 'snapshot WIP' <1>
|
||||||
|
$ git checkout master
|
||||||
|
$ fix fix fix
|
||||||
|
$ git commit ;# commit with real log
|
||||||
|
$ git checkout feature
|
||||||
|
$ git reset --soft HEAD^ ;# go back to WIP state <2>
|
||||||
|
$ git reset <3>
|
||||||
|
|
||||||
|
<1> This commit will get blown away so a throw-away log message is OK.
|
||||||
|
<2> This removes the 'WIP' commit from the commit history, and sets
|
||||||
|
your working tree to the state just before you made that snapshot.
|
||||||
|
<3> After <2>, the index file still has all the WIP changes you
|
||||||
|
committed in <1>. This sets it to the last commit you were
|
||||||
|
basing the WIP changes on.
|
||||||
|
------------
|
||||||
|
|
||||||
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>
|
||||||
@ -156,4 +182,3 @@ Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
|||||||
GIT
|
GIT
|
||||||
---
|
---
|
||||||
Part of the gitlink:git[7] suite
|
Part of the gitlink:git[7] suite
|
||||||
|
|
||||||
|
@ -8,16 +8,18 @@ git-rev-list - Lists commit objects in reverse chronological order
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
|
[verse]
|
||||||
'git-rev-list' [ \--max-count=number ]
|
'git-rev-list' [ \--max-count=number ]
|
||||||
[ \--max-age=timestamp ]
|
[ \--max-age=timestamp ]
|
||||||
[ \--min-age=timestamp ]
|
[ \--min-age=timestamp ]
|
||||||
[ \--sparse ]
|
[ \--sparse ]
|
||||||
[ \--no-merges ]
|
[ \--no-merges ]
|
||||||
|
[ \--remove-empty ]
|
||||||
[ \--all ]
|
[ \--all ]
|
||||||
[ [ \--merge-order [ \--show-breaks ] ] | [ \--topo-order ] | ]
|
[ [ \--merge-order [ \--show-breaks ] ] | [ \--topo-order ] ]
|
||||||
[ \--parents ]
|
[ \--parents ]
|
||||||
[ \--objects [ \--unpacked ] ]
|
[ \--objects [ \--unpacked ] ]
|
||||||
[ \--pretty | \--header | ]
|
[ \--pretty | \--header ]
|
||||||
[ \--bisect ]
|
[ \--bisect ]
|
||||||
<commit>... [ \-- <paths>... ]
|
<commit>... [ \-- <paths>... ]
|
||||||
|
|
||||||
@ -79,6 +81,9 @@ OPTIONS
|
|||||||
(still subject to count and age limitation), but apply
|
(still subject to count and age limitation), but apply
|
||||||
merge simplification nevertheless.
|
merge simplification nevertheless.
|
||||||
|
|
||||||
|
--remove-empty::
|
||||||
|
Stop when a given path disappears from the tree.
|
||||||
|
|
||||||
--all::
|
--all::
|
||||||
Pretend as if all the refs in `$GIT_DIR/refs/` are
|
Pretend as if all the refs in `$GIT_DIR/refs/` are
|
||||||
listed on the command line as <commit>.
|
listed on the command line as <commit>.
|
||||||
@ -129,7 +134,7 @@ the marked commit in the list.
|
|||||||
+
|
+
|
||||||
Commits marked with (^) are not parents of the immediately preceding commit.
|
Commits marked with (^) are not parents of the immediately preceding commit.
|
||||||
These "breaks" represent necessary discontinuities implied by trying to
|
These "breaks" represent necessary discontinuities implied by trying to
|
||||||
represent an arbtirary DAG in a linear form.
|
represent an arbitrary DAG in a linear form.
|
||||||
+
|
+
|
||||||
`--show-breaks` is only valid if `--merge-order` is also specified.
|
`--show-breaks` is only valid if `--merge-order` is also specified.
|
||||||
|
|
||||||
|
@ -68,10 +68,15 @@ OPTIONS
|
|||||||
Show all refs found in `$GIT_DIR/refs`.
|
Show all refs found in `$GIT_DIR/refs`.
|
||||||
|
|
||||||
--show-prefix::
|
--show-prefix::
|
||||||
When the command is invoked from a directory show the
|
When the command is invoked from a subdirectory, show the
|
||||||
path of the current directory relative to the top-level
|
path of the current directory relative to the top-level
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
|
--show-cdup::
|
||||||
|
When the command is invoked from a subdirectory, show the
|
||||||
|
path of the top-level directory relative to the current
|
||||||
|
directory (typically a sequence of "../", or an empty string).
|
||||||
|
|
||||||
--since=datestring, --after=datestring::
|
--since=datestring, --after=datestring::
|
||||||
Parses the date string, and outputs corresponding
|
Parses the date string, and outputs corresponding
|
||||||
--max-age= parameter for git-rev-list command.
|
--max-age= parameter for git-rev-list command.
|
||||||
|
@ -24,32 +24,6 @@ OPTIONS
|
|||||||
-------
|
-------
|
||||||
The options available are:
|
The options available are:
|
||||||
|
|
||||||
--to::
|
|
||||||
Specify the primary recipient of the emails generated.
|
|
||||||
Generally, this will be the upstream maintainer of the
|
|
||||||
project involved.
|
|
||||||
|
|
||||||
--from::
|
|
||||||
Specify the sender of the emails. This will default to
|
|
||||||
the value GIT_COMMITTER_IDENT, as returned by "git-var -l".
|
|
||||||
The user will still be prompted to confirm this entry.
|
|
||||||
|
|
||||||
--compose::
|
|
||||||
Use \$EDITOR to edit an introductory message for the
|
|
||||||
patch series.
|
|
||||||
|
|
||||||
--subject::
|
|
||||||
Specify the initial subject of the email thread.
|
|
||||||
Only necessary if --compose is also set. If --compose
|
|
||||||
is not set, this will be prompted for.
|
|
||||||
|
|
||||||
--in-reply-to::
|
|
||||||
Specify the contents of the first In-Reply-To header.
|
|
||||||
Subsequent emails will refer to the previous email
|
|
||||||
instead of this if --chain-reply-to is set (the default)
|
|
||||||
Only necessary if --compose is also set. If --compose
|
|
||||||
is not set, this will be prompted for.
|
|
||||||
|
|
||||||
--chain-reply-to, --no-chain-reply-to::
|
--chain-reply-to, --no-chain-reply-to::
|
||||||
If this is set, each email will be sent as a reply to the previous
|
If this is set, each email will be sent as a reply to the previous
|
||||||
email sent. If disabled with "--no-chain-reply-to", all emails after
|
email sent. If disabled with "--no-chain-reply-to", all emails after
|
||||||
@ -58,10 +32,40 @@ The options available are:
|
|||||||
entire patch series.
|
entire patch series.
|
||||||
Default is --chain-reply-to
|
Default is --chain-reply-to
|
||||||
|
|
||||||
|
--compose::
|
||||||
|
Use $EDITOR to edit an introductory message for the
|
||||||
|
patch series.
|
||||||
|
|
||||||
|
--from::
|
||||||
|
Specify the sender of the emails. This will default to
|
||||||
|
the value GIT_COMMITTER_IDENT, as returned by "git-var -l".
|
||||||
|
The user will still be prompted to confirm this entry.
|
||||||
|
|
||||||
|
--in-reply-to::
|
||||||
|
Specify the contents of the first In-Reply-To header.
|
||||||
|
Subsequent emails will refer to the previous email
|
||||||
|
instead of this if --chain-reply-to is set (the default)
|
||||||
|
Only necessary if --compose is also set. If --compose
|
||||||
|
is not set, this will be prompted for.
|
||||||
|
|
||||||
|
--quiet::
|
||||||
|
Make git-send-email less verbose. One line per email should be
|
||||||
|
all that is output.
|
||||||
|
|
||||||
--smtp-server::
|
--smtp-server::
|
||||||
If set, specifies the outgoing SMTP server to use. Defaults to
|
If set, specifies the outgoing SMTP server to use. Defaults to
|
||||||
localhost.
|
localhost.
|
||||||
|
|
||||||
|
--subject::
|
||||||
|
Specify the initial subject of the email thread.
|
||||||
|
Only necessary if --compose is also set. If --compose
|
||||||
|
is not set, this will be prompted for.
|
||||||
|
|
||||||
|
--to::
|
||||||
|
Specify the primary recipient of the emails generated.
|
||||||
|
Generally, this will be the upstream maintainer of the
|
||||||
|
project involved.
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
@ -7,7 +7,10 @@ git-show-branch - Show branches and their commits.
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-show-branch [--all] [--heads] [--tags] [--topo-order] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [<rev> | <glob>]...'
|
[verse]
|
||||||
|
git-show-branch [--all] [--heads] [--tags] [--topo-order] [--current]
|
||||||
|
[--more=<n> | --list | --independent | --merge-base]
|
||||||
|
[--no-name | --sha1-name] [<rev> | <glob>]...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -18,6 +21,9 @@ and/or $GIT_DIR/refs/tags) semi-visually.
|
|||||||
|
|
||||||
It cannot show more than 29 branches and commits at a time.
|
It cannot show more than 29 branches and commits at a time.
|
||||||
|
|
||||||
|
It uses `showbranch.default` multi-valued configuration items if
|
||||||
|
no <rev> nor <glob> is given on the command line.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
@ -35,6 +41,11 @@ OPTIONS
|
|||||||
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.
|
||||||
|
|
||||||
|
--current::
|
||||||
|
With this option, the command includes the current
|
||||||
|
branch to the list of revs to be shown when it is not
|
||||||
|
given on the command line.
|
||||||
|
|
||||||
--topo-order::
|
--topo-order::
|
||||||
By default, the branches and their commits are shown in
|
By default, the branches and their commits are shown in
|
||||||
reverse chronological order. This option makes them
|
reverse chronological order. This option makes them
|
||||||
@ -50,7 +61,7 @@ OPTIONS
|
|||||||
tree.
|
tree.
|
||||||
|
|
||||||
--list::
|
--list::
|
||||||
Synomym to `--more=-1`
|
Synonym to `--more=-1`
|
||||||
|
|
||||||
--merge-base::
|
--merge-base::
|
||||||
Instead of showing the commit list, just act like the
|
Instead of showing the commit list, just act like the
|
||||||
@ -78,21 +89,22 @@ OUTPUT
|
|||||||
------
|
------
|
||||||
Given N <references>, the first N lines are the one-line
|
Given N <references>, the first N lines are the one-line
|
||||||
description from their commit message. The branch head that is
|
description from their commit message. The branch head that is
|
||||||
pointed at by $GIT_DIR/HEAD is prefixed with an asterisk '*'
|
pointed at by $GIT_DIR/HEAD is prefixed with an asterisk `*`
|
||||||
character while other heads are prefixed with a '!' character.
|
character while other heads are prefixed with a `!` character.
|
||||||
|
|
||||||
Following these N lines, one-line log for each commit is
|
Following these N lines, one-line log for each commit is
|
||||||
displayed, indented N places. If a commit is on the I-th
|
displayed, indented N places. If a commit is on the I-th
|
||||||
branch, the I-th indentation character shows a '+' sign;
|
branch, the I-th indentation character shows a `+` sign;
|
||||||
otherwise it shows a space. Each commit shows a short name that
|
otherwise it shows a space. Merge commits are denoted by
|
||||||
can be used as an exended SHA1 to name that commit.
|
a `-` sign. Each commit shows a short name that
|
||||||
|
can be used as an extended SHA1 to name that commit.
|
||||||
|
|
||||||
The following example shows three branches, "master", "fixes"
|
The following example shows three branches, "master", "fixes"
|
||||||
and "mhf":
|
and "mhf":
|
||||||
|
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
$ git show-branch master fixes mhf
|
$ git show-branch master fixes mhf
|
||||||
! [master] Add 'git show-branch'.
|
* [master] Add 'git show-branch'.
|
||||||
! [fixes] Introduce "reset type" flag to "git reset"
|
! [fixes] Introduce "reset type" flag to "git reset"
|
||||||
! [mhf] Allow "+remote:local" refspec to cause --force when fetching.
|
! [mhf] Allow "+remote:local" refspec to cause --force when fetching.
|
||||||
---
|
---
|
||||||
@ -106,13 +118,33 @@ $ git show-branch master fixes mhf
|
|||||||
+ [mhf~6] Retire git-parse-remote.
|
+ [mhf~6] Retire git-parse-remote.
|
||||||
+ [mhf~7] Multi-head fetch.
|
+ [mhf~7] Multi-head fetch.
|
||||||
+ [mhf~8] Start adding the $GIT_DIR/remotes/ support.
|
+ [mhf~8] Start adding the $GIT_DIR/remotes/ support.
|
||||||
+++ [master] Add 'git show-branch'.
|
*++ [master] Add 'git show-branch'.
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
These three branches all forked from a common commit, [master],
|
These three branches all forked from a common commit, [master],
|
||||||
whose commit message is "Add 'git show-branch'. "fixes" branch
|
whose commit message is "Add 'git show-branch'. "fixes" branch
|
||||||
adds one commit 'Introduce "reset type"'. "mhf" branch has many
|
adds one commit 'Introduce "reset type"'. "mhf" branch has many
|
||||||
other commits.
|
other commits. The current branch is "master".
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLE
|
||||||
|
-------
|
||||||
|
|
||||||
|
If you keep your primary branches immediately under
|
||||||
|
`$GIT_DIR/refs/heads`, and topic branches in subdirectories of
|
||||||
|
it, having the following in the configuration file may help:
|
||||||
|
|
||||||
|
------------
|
||||||
|
[showbranch]
|
||||||
|
default = --topo-order
|
||||||
|
default = heads/*
|
||||||
|
|
||||||
|
------------
|
||||||
|
|
||||||
|
With this,`git show-branch` without extra parameters would show
|
||||||
|
only the primary branches. In addition, if you happen to be on
|
||||||
|
your topic branch, it is shown as well.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
|
49
Documentation/git-show.txt
Normal file
49
Documentation/git-show.txt
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
git-show(1)
|
||||||
|
===========
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
git-show - Show one commit with difference it introduces.
|
||||||
|
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
--------
|
||||||
|
'git-show' <option>...
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
Shows commit log and textual diff for a single commit. The
|
||||||
|
command internally invokes 'git-rev-list' piped to
|
||||||
|
'git-diff-tree', and takes command line options for both of
|
||||||
|
these commands. It also presents the merge commit in a special
|
||||||
|
format as produced by 'git-diff-tree --cc'.
|
||||||
|
|
||||||
|
This manual page describes only the most frequently used options.
|
||||||
|
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
<commitid>::
|
||||||
|
ID of the commit to show.
|
||||||
|
|
||||||
|
--pretty=<format>::
|
||||||
|
Controls the output format for the commit logs.
|
||||||
|
<format> can be one of 'raw', 'medium', 'short', 'full',
|
||||||
|
and 'oneline'.
|
||||||
|
|
||||||
|
Author
|
||||||
|
------
|
||||||
|
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||||
|
Junio C Hamano <junkio@cox.net>
|
||||||
|
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
Documentation by David Greaves, Petr Baudis and the git-list <git@vger.kernel.org>.
|
||||||
|
|
||||||
|
This manual page is a stub. You can help the git documentation by expanding it.
|
||||||
|
|
||||||
|
GIT
|
||||||
|
---
|
||||||
|
Part of the gitlink:git[7] suite
|
||||||
|
|
@ -11,7 +11,7 @@ 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_rev]
|
[ -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> ]
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ DESCRIPTION
|
|||||||
Imports a SVN repository into git. It will either create a new
|
Imports a SVN repository into git. It will either create a new
|
||||||
repository, or incrementally import into an existing one.
|
repository, or incrementally import into an existing one.
|
||||||
|
|
||||||
SVN access is done by the SVN:: Perl module.
|
SVN access is done by the SVN::Perl module.
|
||||||
|
|
||||||
git-svnimport assumes that SVN repositories are organized into one
|
git-svnimport assumes that SVN repositories are organized into one
|
||||||
"trunk" directory where the main development happens, "branch/FOO"
|
"trunk" directory where the main development happens, "branch/FOO"
|
||||||
@ -40,17 +40,17 @@ OPTIONS
|
|||||||
-s <start_rev>::
|
-s <start_rev>::
|
||||||
Start importing at this SVN change number. The default is 1.
|
Start importing at this SVN change number. The default is 1.
|
||||||
+
|
+
|
||||||
When importing incementally, you might need to edit the .git/svn2git file.
|
When importing incrementally, you might need to edit the .git/svn2git file.
|
||||||
|
|
||||||
-i::
|
-i::
|
||||||
Import-only: don't perform a checkout after importing. This option
|
Import-only: don't perform a checkout after importing. This option
|
||||||
ensures the working directory and index remain untouched and will
|
ensures the working directory and index remain untouched and will
|
||||||
not create them if they do not exist.
|
not create them if they do not exist.
|
||||||
|
|
||||||
-t <trunk_subdir>::
|
-T <trunk_subdir>::
|
||||||
Name the SVN trunk. Default "trunk".
|
Name the SVN trunk. Default "trunk".
|
||||||
|
|
||||||
-T <tag_subdir>::
|
-t <tag_subdir>::
|
||||||
Name the SVN subdirectory for tags. Default "tags".
|
Name the SVN subdirectory for tags. Default "tags".
|
||||||
|
|
||||||
-b <branch_subdir>::
|
-b <branch_subdir>::
|
||||||
@ -74,8 +74,8 @@ When importing incementally, you might need to edit the .git/svn2git file.
|
|||||||
-l <max_rev>::
|
-l <max_rev>::
|
||||||
Specify a maximum revision number to pull.
|
Specify a maximum revision number to pull.
|
||||||
|
|
||||||
Formerly, this option controlled how many revisions to pull, due to
|
Formerly, this option controlled how many revisions to pull,
|
||||||
SVN memory leaks. (These have been worked around.)
|
due to SVN memory leaks. (These have been worked around.)
|
||||||
|
|
||||||
-v::
|
-v::
|
||||||
Verbosity: let 'svnimport' report what it is doing.
|
Verbosity: let 'svnimport' report what it is doing.
|
||||||
@ -100,11 +100,7 @@ with a 40x error pretty quickly.
|
|||||||
If you're using the "-d" or "-D" option, this is the URL of the SVN
|
If you're using the "-d" or "-D" option, this is the URL of the SVN
|
||||||
repository itself; it usually ends in "/svn".
|
repository itself; it usually ends in "/svn".
|
||||||
|
|
||||||
<SVN_repository_URL>::
|
<path>::
|
||||||
The URL of the SVN module you want to import. For local
|
|
||||||
repositories, use "file:///absolute/path".
|
|
||||||
|
|
||||||
<path>
|
|
||||||
The path to the module you want to check out.
|
The path to the module you want to check out.
|
||||||
|
|
||||||
-h::
|
-h::
|
||||||
|
@ -43,12 +43,13 @@ people. The <<Discussion>> section below contains much useful
|
|||||||
definition and clarification - read that first.
|
definition and clarification - read that first.
|
||||||
|
|
||||||
If you are interested in using git to manage (version control)
|
If you are interested in using git to manage (version control)
|
||||||
projects, use link:everyday.html[Everyday GIT] as a guide to the
|
projects, use link:tutorial.html[The Tutorial] to get you started,
|
||||||
|
and then link:everyday.html[Everyday GIT] as a guide to the
|
||||||
minimum set of commands you need to know for day-to-day work.
|
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
|
Most likely, that will get you started, and you can go a long
|
||||||
way without knowing the low level details too much.
|
way without knowing the low level details too much.
|
||||||
|
|
||||||
The link:tutorial.html[tutorial] document covers how things
|
The link:core-tutorial.html[Core tutorial] document covers how things
|
||||||
internally work.
|
internally work.
|
||||||
|
|
||||||
If you are migrating from CVS, link:cvs-migration.html[cvs
|
If you are migrating from CVS, link:cvs-migration.html[cvs
|
||||||
@ -139,6 +140,9 @@ Interrogation commands
|
|||||||
gitlink:git-cat-file[1]::
|
gitlink:git-cat-file[1]::
|
||||||
Provide content or type/size information for repository objects.
|
Provide content or type/size information for repository objects.
|
||||||
|
|
||||||
|
gitlink:git-describe[1]::
|
||||||
|
Show the most recent tag that is reachable from a commit.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
@ -309,6 +313,9 @@ gitlink:git-rebase[1]::
|
|||||||
gitlink:git-repack[1]::
|
gitlink:git-repack[1]::
|
||||||
Pack unpacked objects in a repository.
|
Pack unpacked objects in a repository.
|
||||||
|
|
||||||
|
gitlink:git-rerere[1]::
|
||||||
|
Reuse recorded resolution of conflicted merges.
|
||||||
|
|
||||||
gitlink:git-reset[1]::
|
gitlink:git-reset[1]::
|
||||||
Reset current HEAD to the specified state.
|
Reset current HEAD to the specified state.
|
||||||
|
|
||||||
@ -422,7 +429,7 @@ gitlink:git-rev-parse[1]::
|
|||||||
gitlink:git-send-email[1]::
|
gitlink:git-send-email[1]::
|
||||||
Send patch e-mails out of "format-patch --mbox" output.
|
Send patch e-mails out of "format-patch --mbox" output.
|
||||||
|
|
||||||
gitlink:git-symbolic-refs[1]::
|
gitlink:git-symbolic-ref[1]::
|
||||||
Read and modify symbolic refs.
|
Read and modify symbolic refs.
|
||||||
|
|
||||||
gitlink:git-stripspace[1]::
|
gitlink:git-stripspace[1]::
|
||||||
@ -582,7 +589,7 @@ git Diffs
|
|||||||
|
|
||||||
Discussion[[Discussion]]
|
Discussion[[Discussion]]
|
||||||
------------------------
|
------------------------
|
||||||
include::../README[]
|
include::README[]
|
||||||
|
|
||||||
Authors
|
Authors
|
||||||
-------
|
-------
|
||||||
|
@ -19,7 +19,7 @@ hash::
|
|||||||
In git's context, synonym to object name.
|
In git's context, synonym to object name.
|
||||||
|
|
||||||
object database::
|
object database::
|
||||||
Stores a set of "objects", and an individial object is identified
|
Stores a set of "objects", and an individual object is identified
|
||||||
by its object name. The objects usually live in `$GIT_DIR/objects/`.
|
by its object name. The objects usually live in `$GIT_DIR/objects/`.
|
||||||
|
|
||||||
blob object::
|
blob object::
|
||||||
@ -111,6 +111,17 @@ branch::
|
|||||||
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/`.
|
||||||
|
|
||||||
|
master::
|
||||||
|
The default branch. Whenever you create a git repository, a branch
|
||||||
|
named "master" is created, and becomes the active branch. In most
|
||||||
|
cases, this contains the local development.
|
||||||
|
|
||||||
|
origin::
|
||||||
|
The default upstream branch. Most projects have one upstream
|
||||||
|
project which they track, and by default 'origin' is used for
|
||||||
|
that purpose. New updates from upstream will be fetched into
|
||||||
|
this branch; you should never commit to it yourself.
|
||||||
|
|
||||||
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/`.
|
||||||
|
@ -24,7 +24,7 @@ Then do
|
|||||||
git bisect bad master <- mark "master" as the bad state
|
git bisect bad master <- mark "master" as the bad state
|
||||||
git bisect good ORIG_HEAD <- mark ORIG_HEAD as good (or
|
git bisect good ORIG_HEAD <- mark ORIG_HEAD as good (or
|
||||||
whatever other known-good
|
whatever other known-good
|
||||||
thing you booted laste)
|
thing you booted last)
|
||||||
|
|
||||||
and at this point "git bisect" will churn for a while, and tell you what
|
and at this point "git bisect" will churn for a while, and tell you what
|
||||||
the mid-point between those two commits are, and check that state out as
|
the mid-point between those two commits are, and check that state out as
|
||||||
|
@ -32,16 +32,16 @@ merge introduced 5 commits or so:
|
|||||||
|
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
$ git show-branch --more=4 master master^2 | head
|
$ git show-branch --more=4 master master^2 | head
|
||||||
! [master] Merge refs/heads/portable from http://www.cs.berkeley....
|
* [master] Merge refs/heads/portable from http://www.cs.berkeley....
|
||||||
! [master^2] Replace C99 array initializers with code.
|
! [master^2] Replace C99 array initializers with code.
|
||||||
--
|
--
|
||||||
+ [master] Merge refs/heads/portable from http://www.cs.berkeley....
|
- [master] Merge refs/heads/portable from http://www.cs.berkeley....
|
||||||
++ [master^2] Replace C99 array initializers with code.
|
*+ [master^2] Replace C99 array initializers with code.
|
||||||
++ [master^2~1] Replace unsetenv() and setenv() with older putenv().
|
*+ [master^2~1] Replace unsetenv() and setenv() with older putenv().
|
||||||
++ [master^2~2] Include sys/time.h in daemon.c.
|
*+ [master^2~2] Include sys/time.h in daemon.c.
|
||||||
++ [master^2~3] Fix ?: statements.
|
*+ [master^2~3] Fix ?: statements.
|
||||||
++ [master^2~4] Replace zero-length array decls with [].
|
*+ [master^2~4] Replace zero-length array decls with [].
|
||||||
+ [master~1] tutorial note about git branch
|
* [master~1] tutorial note about git branch
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
The '--more=4' above means "after we reach the merge base of refs,
|
The '--more=4' above means "after we reach the merge base of refs,
|
||||||
@ -193,8 +193,8 @@ $ git show-branch --more=1 master pu rc
|
|||||||
+ [pu~4] Document "git cherry-pick" and "git revert"
|
+ [pu~4] Document "git cherry-pick" and "git revert"
|
||||||
+ [pu~5] Remove git-apply-patch-script.
|
+ [pu~5] Remove git-apply-patch-script.
|
||||||
+ [pu~6] Redo "revert" using three-way merge machinery.
|
+ [pu~6] Redo "revert" using three-way merge machinery.
|
||||||
+ [rc] Merge refs/heads/master from .
|
- [rc] Merge refs/heads/master from .
|
||||||
+++ [master] Revert "Replace zero-length array decls with []."
|
++* [master] Revert "Replace zero-length array decls with []."
|
||||||
+ [rc~1] Merge refs/heads/master from .
|
- [rc~1] Merge refs/heads/master from .
|
||||||
+++ [master~1] Merge refs/heads/portable from http://www.cs.berkeley....
|
... [master~1] Merge refs/heads/portable from http://www.cs.berkeley....
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
91
Documentation/howto/separating-topic-branches.txt
Normal file
91
Documentation/howto/separating-topic-branches.txt
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
From: Junio C Hamano <junkio@cox.net>
|
||||||
|
Subject: Separating topic branches
|
||||||
|
Abstract: In this article, JC describes how to separate topic branches.
|
||||||
|
|
||||||
|
This text was originally a footnote to a discussion about the
|
||||||
|
behaviour of the git diff commands.
|
||||||
|
|
||||||
|
Often I find myself doing that [running diff against something other
|
||||||
|
than HEAD] while rewriting messy development history. For example, I
|
||||||
|
start doing some work without knowing exactly where it leads, and end
|
||||||
|
up with a history like this:
|
||||||
|
|
||||||
|
"master"
|
||||||
|
o---o
|
||||||
|
\ "topic"
|
||||||
|
o---o---o---o---o---o
|
||||||
|
|
||||||
|
At this point, "topic" contains something I know I want, but it
|
||||||
|
contains two concepts that turned out to be completely independent.
|
||||||
|
And often, one topic component is larger than the other. It may
|
||||||
|
contain more than two topics.
|
||||||
|
|
||||||
|
In order to rewrite this mess to be more manageable, I would first do
|
||||||
|
"diff master..topic", to extract the changes into a single patch, start
|
||||||
|
picking pieces from it to get logically self-contained units, and
|
||||||
|
start building on top of "master":
|
||||||
|
|
||||||
|
$ git diff master..topic >P.diff
|
||||||
|
$ git checkout -b topicA master
|
||||||
|
... pick and apply pieces from P.diff to build
|
||||||
|
... commits on topicA branch.
|
||||||
|
|
||||||
|
o---o---o
|
||||||
|
/ "topicA"
|
||||||
|
o---o"master"
|
||||||
|
\ "topic"
|
||||||
|
o---o---o---o---o---o
|
||||||
|
|
||||||
|
Before doing each commit on "topicA" HEAD, I run "diff HEAD"
|
||||||
|
before update-index the affected paths, or "diff --cached HEAD"
|
||||||
|
after. Also I would run "diff --cached master" to make sure
|
||||||
|
that the changes are only the ones related to "topicA". Usually
|
||||||
|
I do this for smaller topics first.
|
||||||
|
|
||||||
|
After that, I'd do the remainder of the original "topic", but
|
||||||
|
for that, I do not start from the patchfile I extracted by
|
||||||
|
comparing "master" and "topic" I used initially. Still on
|
||||||
|
"topicA", I extract "diff topic", and use it to rebuild the
|
||||||
|
other topic:
|
||||||
|
|
||||||
|
$ git diff -R topic >P.diff ;# --cached also would work fine
|
||||||
|
$ git checkout -b topicB master
|
||||||
|
... pick and apply pieces from P.diff to build
|
||||||
|
... commits on topicB branch.
|
||||||
|
|
||||||
|
"topicB"
|
||||||
|
o---o---o---o---o
|
||||||
|
/
|
||||||
|
/o---o---o
|
||||||
|
|/ "topicA"
|
||||||
|
o---o"master"
|
||||||
|
\ "topic"
|
||||||
|
o---o---o---o---o---o
|
||||||
|
|
||||||
|
After I am done, I'd try a pretend-merge between "topicA" and
|
||||||
|
"topicB" in order to make sure I have not missed anything:
|
||||||
|
|
||||||
|
$ git pull . topicA ;# merge it into current "topicB"
|
||||||
|
$ git diff topic
|
||||||
|
"topicB"
|
||||||
|
o---o---o---o---o---* (pretend merge)
|
||||||
|
/ /
|
||||||
|
/o---o---o----------'
|
||||||
|
|/ "topicA"
|
||||||
|
o---o"master"
|
||||||
|
\ "topic"
|
||||||
|
o---o---o---o---o---o
|
||||||
|
|
||||||
|
The last diff better not to show anything other than cleanups
|
||||||
|
for crufts. Then I can finally clean things up:
|
||||||
|
|
||||||
|
$ git branch -D topic
|
||||||
|
$ git reset --hard HEAD^ ;# nuke pretend merge
|
||||||
|
|
||||||
|
"topicB"
|
||||||
|
o---o---o---o---o
|
||||||
|
/
|
||||||
|
/o---o---o
|
||||||
|
|/ "topicA"
|
||||||
|
o---o"master"
|
||||||
|
|
@ -9,7 +9,7 @@ GIT as a Linux subsystem maintainer.
|
|||||||
|
|
||||||
-Tony
|
-Tony
|
||||||
|
|
||||||
Last updated w.r.t. GIT 0.99.9f
|
Last updated w.r.t. GIT 1.1
|
||||||
|
|
||||||
Linux subsystem maintenance using GIT
|
Linux subsystem maintenance using GIT
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
@ -92,6 +92,14 @@ These can be easily kept up to date by merging from the "linus" branch:
|
|||||||
$ git checkout test && git merge "Auto-update from upstream" test linus
|
$ git checkout test && git merge "Auto-update from upstream" test linus
|
||||||
$ git checkout release && git merge "Auto-update from upstream" release linus
|
$ git checkout release && git merge "Auto-update from upstream" release linus
|
||||||
|
|
||||||
|
Important note! If you have any local changes in these branches, then
|
||||||
|
this merge will create a commit object in the history (with no local
|
||||||
|
changes git will simply do a "Fast forward" merge). Many people dislike
|
||||||
|
the "noise" that this creates in the Linux history, so you should avoid
|
||||||
|
doing this capriciously in the "release" branch, as these noisy commits
|
||||||
|
will become part of the permanent history when you ask Linus to pull
|
||||||
|
from the release branch.
|
||||||
|
|
||||||
Set up so that you can push upstream to your public tree (you need to
|
Set up so that you can push upstream to your public tree (you need to
|
||||||
log-in to the remote system and create an empty tree there before the
|
log-in to the remote system and create an empty tree there before the
|
||||||
first push).
|
first push).
|
||||||
|
@ -1,68 +1,6 @@
|
|||||||
<repository>::
|
<repository>::
|
||||||
The "remote" repository that is the source of a fetch
|
The "remote" repository that is the source of a fetch
|
||||||
or pull operation, or the destination of a push operation.
|
or pull operation. See the section <<URLS,GIT URLS>> below.
|
||||||
One of the following notations can be used
|
|
||||||
to name the remote repository:
|
|
||||||
+
|
|
||||||
===============================================================
|
|
||||||
- rsync://host.xz/path/to/repo.git/
|
|
||||||
- http://host.xz/path/to/repo.git/
|
|
||||||
- https://host.xz/path/to/repo.git/
|
|
||||||
- git://host.xz/path/to/repo.git/
|
|
||||||
- git://host.xz/~user/path/to/repo.git/
|
|
||||||
- ssh://host.xz/path/to/repo.git/
|
|
||||||
- ssh://host.xz/~user/path/to/repo.git/
|
|
||||||
- ssh://host.xz/~/path/to/repo.git
|
|
||||||
===============================================================
|
|
||||||
+
|
|
||||||
SSH Is the default transport protocol and also supports an
|
|
||||||
scp-like syntax. Both syntaxes support username expansion,
|
|
||||||
as does the native git protocol. The following three are
|
|
||||||
identical to the last three above, respectively:
|
|
||||||
+
|
|
||||||
===============================================================
|
|
||||||
- host.xz:/path/to/repo.git/
|
|
||||||
- host.xz:~user/path/to/repo.git/
|
|
||||||
- host.xz:path/to/repo.git
|
|
||||||
===============================================================
|
|
||||||
+
|
|
||||||
To sync with a local directory, use:
|
|
||||||
+
|
|
||||||
===============================================================
|
|
||||||
- /path/to/repo.git/
|
|
||||||
===============================================================
|
|
||||||
+
|
|
||||||
In addition to the above, as a short-hand, the name of a
|
|
||||||
file in `$GIT_DIR/remotes` directory can be given; the
|
|
||||||
named file should be in the following format:
|
|
||||||
+
|
|
||||||
URL: one of the above URL format
|
|
||||||
Push: <refspec>
|
|
||||||
Pull: <refspec>
|
|
||||||
+
|
|
||||||
When such a short-hand is specified in place of
|
|
||||||
<repository> without <refspec> parameters on the command
|
|
||||||
line, <refspec> specified on `Push:` lines or `Pull:`
|
|
||||||
lines are used for `git-push` and `git-fetch`/`git-pull`,
|
|
||||||
respectively. Multiple `Push:` and and `Pull:` lines may
|
|
||||||
be specified for additional branch mappings.
|
|
||||||
+
|
|
||||||
The name of a file in `$GIT_DIR/branches` directory can be
|
|
||||||
specified as an older notation short-hand; the named
|
|
||||||
file should contain a single line, a URL in one of the
|
|
||||||
above formats, optionally followed by a hash `#` and the
|
|
||||||
name of remote head (URL fragment notation).
|
|
||||||
`$GIT_DIR/branches/<remote>` file that stores a <url>
|
|
||||||
without the fragment is equivalent to have this in the
|
|
||||||
corresponding file in the `$GIT_DIR/remotes/` directory.
|
|
||||||
+
|
|
||||||
URL: <url>
|
|
||||||
Pull: refs/heads/master:<remote>
|
|
||||||
+
|
|
||||||
while having `<url>#<head>` is equivalent to
|
|
||||||
+
|
|
||||||
URL: <url>
|
|
||||||
Pull: refs/heads/<head>:<remote>
|
|
||||||
|
|
||||||
<refspec>::
|
<refspec>::
|
||||||
The canonical format of a <refspec> parameter is
|
The canonical format of a <refspec> parameter is
|
||||||
@ -70,17 +8,7 @@ while having `<url>#<head>` is equivalent to
|
|||||||
by the source ref, followed by a colon `:`, followed by
|
by the source ref, followed by a colon `:`, followed by
|
||||||
the destination ref.
|
the destination ref.
|
||||||
+
|
+
|
||||||
When used in `git-push`, the <src> side can be an
|
The remote ref that matches <src>
|
||||||
arbitrary "SHA1 expression" that can be used as an
|
|
||||||
argument to `git-cat-file -t`. E.g. `master~4` (push
|
|
||||||
four parents before the current master head).
|
|
||||||
+
|
|
||||||
For `git-push`, the local ref that matches <src> is used
|
|
||||||
to fast forward the remote ref that matches <dst>. If
|
|
||||||
the optional plus `+` is used, the remote ref is updated
|
|
||||||
even if it does not result in a fast forward update.
|
|
||||||
+
|
|
||||||
For `git-fetch` and `git-pull`, the remote ref that matches <src>
|
|
||||||
is fetched, and if <dst> is not empty string, the local
|
is fetched, and if <dst> is not empty string, the local
|
||||||
ref that matches it is fast forwarded using <src>.
|
ref that matches it is fast forwarded using <src>.
|
||||||
Again, if the optional plus `+` is used, the local ref
|
Again, if the optional plus `+` is used, the local ref
|
||||||
@ -134,11 +62,8 @@ is often useful.
|
|||||||
+
|
+
|
||||||
Some short-cut notations are also supported.
|
Some short-cut notations are also supported.
|
||||||
+
|
+
|
||||||
* For backward compatibility, `tag` is almost ignored;
|
* `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`;
|
||||||
it just makes the following parameter <tag> to mean a
|
it requests fetching everything up to the given tag.
|
||||||
refspec `refs/tags/<tag>:refs/tags/<tag>`.
|
|
||||||
* A parameter <ref> without a colon is equivalent to
|
* A parameter <ref> without a colon is equivalent to
|
||||||
<ref>: when pulling/fetching, and <ref>`:`<ref> when
|
<ref>: when pulling/fetching, so it merges <ref> into the current
|
||||||
pushing. That is, do not store it locally if
|
branch without storing the remote branch anywhere locally
|
||||||
fetching, and update the same name if pushing.
|
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ git repository layout
|
|||||||
|
|
||||||
You may find these things in your git repository (`.git`
|
You may find these things in your git repository (`.git`
|
||||||
directory for a repository associated with your working tree, or
|
directory for a repository associated with your working tree, or
|
||||||
`'project'.git` directory for a public 'naked' repository).
|
`'project'.git` directory for a public 'bare' repository).
|
||||||
|
|
||||||
objects::
|
objects::
|
||||||
Object store associated with this repository. Usually
|
Object store associated with this repository. Usually
|
||||||
@ -21,7 +21,7 @@ outside world but sometimes useful for private repository.
|
|||||||
. You can be using `objects/info/alternates` mechanism, or
|
. You can be using `objects/info/alternates` mechanism, or
|
||||||
`$GIT_ALTERNATE_OBJECT_DIRECTORIES` mechanism to 'borrow'
|
`$GIT_ALTERNATE_OBJECT_DIRECTORIES` mechanism to 'borrow'
|
||||||
objects from other object stores. A repository with this kind
|
objects from other object stores. A repository with this kind
|
||||||
of incompete object store is not suitable to be published for
|
of incomplete object store is not suitable to be published for
|
||||||
use with dumb transports but otherwise is OK as long as
|
use with dumb transports but otherwise is OK as long as
|
||||||
`objects/info/alternates` points at the right object stores
|
`objects/info/alternates` points at the right object stores
|
||||||
it borrows from.
|
it borrows from.
|
||||||
@ -73,7 +73,7 @@ HEAD::
|
|||||||
A symlink of the form `refs/heads/'name'` to point at
|
A symlink of the form `refs/heads/'name'` to point at
|
||||||
the current branch, if exists. It does not mean much if
|
the current branch, if exists. It does not mean much if
|
||||||
the repository is not associated with any working tree
|
the repository is not associated with any working tree
|
||||||
(i.e. 'naked' repository), but a valid git repository
|
(i.e. a 'bare' repository), but a valid git repository
|
||||||
*must* have such a symlink here. It is legal if the
|
*must* have such a symlink here. It is legal if the
|
||||||
named branch 'name' does not (yet) exist.
|
named branch 'name' does not (yet) exist.
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ hooks::
|
|||||||
|
|
||||||
index::
|
index::
|
||||||
The current index file for the repository. It is
|
The current index file for the repository. It is
|
||||||
usually not found in a naked repository.
|
usually not found in a bare repository.
|
||||||
|
|
||||||
info::
|
info::
|
||||||
Additional information about the repository is recorded
|
Additional information about the repository is recorded
|
||||||
@ -106,7 +106,7 @@ info/refs::
|
|||||||
up-to-date if the repository is published for dumb
|
up-to-date if the repository is published for dumb
|
||||||
transports. The `git-receive-pack` command, which is
|
transports. The `git-receive-pack` command, which is
|
||||||
run on a remote repository when you `git push` into it,
|
run on a remote repository when you `git push` into it,
|
||||||
runs `hooks/update` hook to help you achive this.
|
runs `hooks/update` hook to help you achieve this.
|
||||||
|
|
||||||
info/grafts::
|
info/grafts::
|
||||||
This file records fake commit ancestry information, to
|
This file records fake commit ancestry information, to
|
||||||
|
File diff suppressed because it is too large
Load Diff
68
Documentation/urls.txt
Normal file
68
Documentation/urls.txt
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
GIT URLS[[URLS]]
|
||||||
|
----------------
|
||||||
|
|
||||||
|
One of the following notations can be used
|
||||||
|
to name the remote repository:
|
||||||
|
|
||||||
|
===============================================================
|
||||||
|
- rsync://host.xz/path/to/repo.git/
|
||||||
|
- http://host.xz/path/to/repo.git/
|
||||||
|
- https://host.xz/path/to/repo.git/
|
||||||
|
- git://host.xz/path/to/repo.git/
|
||||||
|
- git://host.xz/~user/path/to/repo.git/
|
||||||
|
- ssh://host.xz/path/to/repo.git/
|
||||||
|
- ssh://host.xz/~user/path/to/repo.git/
|
||||||
|
- ssh://host.xz/~/path/to/repo.git
|
||||||
|
===============================================================
|
||||||
|
|
||||||
|
SSH Is the default transport protocol and also supports an
|
||||||
|
scp-like syntax. Both syntaxes support username expansion,
|
||||||
|
as does the native git protocol. The following three are
|
||||||
|
identical to the last three above, respectively:
|
||||||
|
|
||||||
|
===============================================================
|
||||||
|
- host.xz:/path/to/repo.git/
|
||||||
|
- host.xz:~user/path/to/repo.git/
|
||||||
|
- host.xz:path/to/repo.git
|
||||||
|
===============================================================
|
||||||
|
|
||||||
|
To sync with a local directory, use:
|
||||||
|
|
||||||
|
===============================================================
|
||||||
|
- /path/to/repo.git/
|
||||||
|
===============================================================
|
||||||
|
|
||||||
|
REMOTES
|
||||||
|
-------
|
||||||
|
|
||||||
|
In addition to the above, as a short-hand, the name of a
|
||||||
|
file in `$GIT_DIR/remotes` directory can be given; the
|
||||||
|
named file should be in the following format:
|
||||||
|
|
||||||
|
URL: one of the above URL format
|
||||||
|
Push: <refspec>
|
||||||
|
Pull: <refspec>
|
||||||
|
|
||||||
|
Then such a short-hand is specified in place of
|
||||||
|
<repository> without <refspec> parameters on the command
|
||||||
|
line, <refspec> specified on `Push:` lines or `Pull:`
|
||||||
|
lines are used for `git-push` and `git-fetch`/`git-pull`,
|
||||||
|
respectively. Multiple `Push:` and and `Pull:` lines may
|
||||||
|
be specified for additional branch mappings.
|
||||||
|
|
||||||
|
The name of a file in `$GIT_DIR/branches` directory can be
|
||||||
|
specified as an older notation short-hand; the named
|
||||||
|
file should contain a single line, a URL in one of the
|
||||||
|
above formats, optionally followed by a hash `#` and the
|
||||||
|
name of remote head (URL fragment notation).
|
||||||
|
`$GIT_DIR/branches/<remote>` file that stores a <url>
|
||||||
|
without the fragment is equivalent to have this in the
|
||||||
|
corresponding file in the `$GIT_DIR/remotes/` directory.
|
||||||
|
|
||||||
|
URL: <url>
|
||||||
|
Pull: refs/heads/master:<remote>
|
||||||
|
|
||||||
|
while having `<url>#<head>` is equivalent to
|
||||||
|
|
||||||
|
URL: <url>
|
||||||
|
Pull: refs/heads/<head>:<remote>
|
35
GIT-VERSION-GEN
Executable file
35
GIT-VERSION-GEN
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
GVF=GIT-VERSION-FILE
|
||||||
|
DEF_VER=v1.2.GIT
|
||||||
|
|
||||||
|
# First try git-describe, then see if there is a version file
|
||||||
|
# (included in release tarballs), then default
|
||||||
|
if VN=$(git-describe --abbrev=4 HEAD 2>/dev/null); then
|
||||||
|
VN=$(echo "$VN" | sed -e 's/-/./g');
|
||||||
|
else
|
||||||
|
VN=$(cat version) || VN="$DEF_VER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
VN=$(expr "$VN" : v*'\(.*\)')
|
||||||
|
|
||||||
|
dirty=$(sh -c 'git-diff-index --name-only HEAD' 2>/dev/null) || dirty=
|
||||||
|
case "$dirty" in
|
||||||
|
'')
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
VN="$VN-dirty" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -r $GVF
|
||||||
|
then
|
||||||
|
VC=$(sed -e 's/^GIT_VERSION = //' <$GVF)
|
||||||
|
else
|
||||||
|
VC=unset
|
||||||
|
fi
|
||||||
|
test "$VN" = "$VC" || {
|
||||||
|
echo >&2 "GIT_VERSION = $VN"
|
||||||
|
echo "GIT_VERSION = $VN" >$GVF
|
||||||
|
}
|
||||||
|
|
||||||
|
|
28
INSTALL
28
INSTALL
@ -5,8 +5,8 @@ Normally you can just do "make" followed by "make install", and that
|
|||||||
will install the git programs in your own ~/bin/ directory. If you want
|
will install the git programs in your own ~/bin/ directory. If you want
|
||||||
to do a global install, you can do
|
to do a global install, you can do
|
||||||
|
|
||||||
$ make prefix=/usr ;# as yourself
|
$ make prefix=/usr all doc ;# as yourself
|
||||||
# make prefix=/usr install ;# as root
|
# make prefix=/usr install install-doc ;# as root
|
||||||
|
|
||||||
(or prefix=/usr/local, of course). Just like any program suite
|
(or prefix=/usr/local, of course). Just like any program suite
|
||||||
that uses $prefix, the built results have some paths encoded,
|
that uses $prefix, the built results have some paths encoded,
|
||||||
@ -90,3 +90,27 @@ Issues of note:
|
|||||||
You can place local settings in config.mak and the Makefile
|
You can place local settings in config.mak and the Makefile
|
||||||
will include them. Note that config.mak is not distributed;
|
will include them. Note that config.mak is not distributed;
|
||||||
the name is reserved for local settings.
|
the name is reserved for local settings.
|
||||||
|
|
||||||
|
- To build and install documentation suite, you need to have the
|
||||||
|
asciidoc/xmlto toolchain. Alternatively, pre-formatted
|
||||||
|
documentation are available in "html" and "man" branches of the git
|
||||||
|
repository itself. For example, you could:
|
||||||
|
|
||||||
|
$ mkdir manual && cd manual
|
||||||
|
$ git init-db
|
||||||
|
$ git clone-pack git://git.kernel.org/pub/scm/git/git.git man html |
|
||||||
|
while read a b
|
||||||
|
do
|
||||||
|
echo $a >.git/$b
|
||||||
|
done
|
||||||
|
$ cp .git/refs/heads/man .git/refs/heads/master
|
||||||
|
$ git checkout
|
||||||
|
|
||||||
|
to checkout the pre-built man pages. Also in this repository:
|
||||||
|
|
||||||
|
$ git checkout html
|
||||||
|
|
||||||
|
would instead give you a copy of what you see at:
|
||||||
|
|
||||||
|
http://www.kernel.org/pub/software/scm/git/docs/
|
||||||
|
|
||||||
|
113
Makefile
113
Makefile
@ -19,10 +19,18 @@ all:
|
|||||||
# Define NO_EXPAT if you do not have expat installed. git-http-push is
|
# Define NO_EXPAT if you do not have expat installed. git-http-push is
|
||||||
# not built, and you cannot push using http:// and https:// transports.
|
# not built, and you cannot push using http:// and https:// transports.
|
||||||
#
|
#
|
||||||
|
# Define NO_D_INO_IN_DIRENT if you don't have d_ino in your struct dirent.
|
||||||
|
#
|
||||||
|
# Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
|
||||||
|
# d_type in struct dirent (latest Cygwin -- will be fixed soonish).
|
||||||
|
#
|
||||||
# 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 NO_SETENV if you don't have setenv in the C library.
|
||||||
#
|
#
|
||||||
|
# Define USE_SYMLINK_HEAD if you want .git/HEAD to be a symbolic link.
|
||||||
|
# Don't enable it on Windows.
|
||||||
|
#
|
||||||
# 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.
|
||||||
#
|
#
|
||||||
@ -42,6 +50,9 @@ all:
|
|||||||
#
|
#
|
||||||
# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
|
# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
|
||||||
#
|
#
|
||||||
|
# Define NO_SOCKADDR_STORAGE if your platform does not have struct
|
||||||
|
# sockaddr_storage.
|
||||||
|
#
|
||||||
# Define COLLISION_CHECK below if you believe that SHA1's
|
# Define COLLISION_CHECK below if you believe that SHA1's
|
||||||
# 1461501637330902918203684832716283019655932542976 hashes do not give you
|
# 1461501637330902918203684832716283019655932542976 hashes do not give you
|
||||||
# sufficient guarantee that no collisions between objects will ever happen.
|
# sufficient guarantee that no collisions between objects will ever happen.
|
||||||
@ -55,7 +66,9 @@ all:
|
|||||||
# 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 = 1.0.0a
|
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
||||||
|
@$(SHELL) ./GIT-VERSION-GEN
|
||||||
|
-include GIT-VERSION-FILE
|
||||||
|
|
||||||
# CFLAGS and LDFLAGS are for the users to override from the command line.
|
# CFLAGS and LDFLAGS are for the users to override from the command line.
|
||||||
|
|
||||||
@ -63,9 +76,11 @@ CFLAGS = -g -O2 -Wall
|
|||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
ALL_CFLAGS = $(CFLAGS)
|
ALL_CFLAGS = $(CFLAGS)
|
||||||
ALL_LDFLAGS = $(LDFLAGS)
|
ALL_LDFLAGS = $(LDFLAGS)
|
||||||
|
STRIP ?= strip
|
||||||
|
|
||||||
prefix = $(HOME)
|
prefix = $(HOME)
|
||||||
bindir = $(prefix)/bin
|
bindir = $(prefix)/bin
|
||||||
|
gitexecdir = $(prefix)/bin
|
||||||
template_dir = $(prefix)/share/git-core/templates/
|
template_dir = $(prefix)/share/git-core/templates/
|
||||||
GIT_PYTHON_DIR = $(prefix)/share/git-core/python
|
GIT_PYTHON_DIR = $(prefix)/share/git-core/python
|
||||||
# DESTDIR=
|
# DESTDIR=
|
||||||
@ -92,7 +107,7 @@ SCRIPT_SH = \
|
|||||||
git-merge-one-file.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-tag.sh git-verify-tag.sh git-whatchanged.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 \
|
||||||
@ -101,7 +116,7 @@ SCRIPT_SH = \
|
|||||||
|
|
||||||
SCRIPT_PERL = \
|
SCRIPT_PERL = \
|
||||||
git-archimport.perl git-cvsimport.perl git-relink.perl \
|
git-archimport.perl git-cvsimport.perl git-relink.perl \
|
||||||
git-shortlog.perl git-fmt-merge-msg.perl \
|
git-shortlog.perl git-fmt-merge-msg.perl git-rerere.perl \
|
||||||
git-svnimport.perl git-mv.perl git-cvsexportcommit.perl
|
git-svnimport.perl git-mv.perl git-cvsexportcommit.perl
|
||||||
|
|
||||||
SCRIPT_PYTHON = \
|
SCRIPT_PYTHON = \
|
||||||
@ -110,14 +125,14 @@ SCRIPT_PYTHON = \
|
|||||||
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
|
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
|
||||||
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
|
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
|
||||||
$(patsubst %.py,%,$(SCRIPT_PYTHON)) \
|
$(patsubst %.py,%,$(SCRIPT_PYTHON)) \
|
||||||
gitk git-cherry-pick
|
git-cherry-pick git-show git-status
|
||||||
|
|
||||||
# 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-daemon$X
|
git-stripspace$X git-daemon$X
|
||||||
|
|
||||||
# ... and all the rest
|
# ... and all the rest that could be moved out of bindir to gitexecdir
|
||||||
PROGRAMS = \
|
PROGRAMS = \
|
||||||
git-apply$X git-cat-file$X \
|
git-apply$X git-cat-file$X \
|
||||||
git-checkout-index$X git-clone-pack$X git-commit-tree$X \
|
git-checkout-index$X git-clone-pack$X git-commit-tree$X \
|
||||||
@ -135,10 +150,11 @@ 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 git-repo-config$X git-var$X
|
git-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \
|
||||||
|
git-describe$X
|
||||||
|
|
||||||
# what 'all' will build and 'install' will install.
|
# what 'all' will build and 'install' will install, in gitexecdir
|
||||||
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS) git$X
|
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
|
||||||
|
|
||||||
# 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
|
||||||
@ -166,11 +182,11 @@ LIB_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 \
|
||||||
diffcore-pickaxe.o diffcore-rename.o tree-diff.o
|
diffcore-pickaxe.o diffcore-rename.o tree-diff.o combine-diff.o
|
||||||
|
|
||||||
LIB_OBJS = \
|
LIB_OBJS = \
|
||||||
blob.o commit.o connect.o count-delta.o csum-file.o \
|
blob.o commit.o connect.o count-delta.o csum-file.o \
|
||||||
date.o diff-delta.o entry.o ident.o index.o \
|
date.o diff-delta.o entry.o exec_cmd.o ident.o index.o \
|
||||||
object.o pack-check.o patch-delta.o path.o pkt-line.o \
|
object.o pack-check.o patch-delta.o path.o pkt-line.o \
|
||||||
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 \
|
||||||
@ -216,6 +232,7 @@ ifeq ($(uname_S),SunOS)
|
|||||||
SHELL_PATH = /bin/bash
|
SHELL_PATH = /bin/bash
|
||||||
NO_STRCASESTR = YesPlease
|
NO_STRCASESTR = YesPlease
|
||||||
ifeq ($(uname_R),5.8)
|
ifeq ($(uname_R),5.8)
|
||||||
|
NO_UNSETENV = YesPlease
|
||||||
NO_SETENV = YesPlease
|
NO_SETENV = YesPlease
|
||||||
endif
|
endif
|
||||||
INSTALL = ginstall
|
INSTALL = ginstall
|
||||||
@ -223,6 +240,8 @@ ifeq ($(uname_S),SunOS)
|
|||||||
ALL_CFLAGS += -D__EXTENSIONS__
|
ALL_CFLAGS += -D__EXTENSIONS__
|
||||||
endif
|
endif
|
||||||
ifeq ($(uname_O),Cygwin)
|
ifeq ($(uname_O),Cygwin)
|
||||||
|
NO_D_TYPE_IN_DIRENT = YesPlease
|
||||||
|
NO_D_INO_IN_DIRENT = YesPlease
|
||||||
NO_STRCASESTR = YesPlease
|
NO_STRCASESTR = YesPlease
|
||||||
NEEDS_LIBICONV = YesPlease
|
NEEDS_LIBICONV = YesPlease
|
||||||
# There are conflicting reports about this.
|
# There are conflicting reports about this.
|
||||||
@ -231,7 +250,11 @@ ifeq ($(uname_O),Cygwin)
|
|||||||
# NO_MMAP = YesPlease
|
# NO_MMAP = YesPlease
|
||||||
NO_IPV6 = YesPlease
|
NO_IPV6 = YesPlease
|
||||||
X = .exe
|
X = .exe
|
||||||
ALL_CFLAGS += -DUSE_SYMLINK_HEAD=0
|
endif
|
||||||
|
ifeq ($(uname_S),FreeBSD)
|
||||||
|
NEEDS_LIBICONV = YesPlease
|
||||||
|
ALL_CFLAGS += -I/usr/local/include
|
||||||
|
ALL_LDFLAGS += -L/usr/local/lib
|
||||||
endif
|
endif
|
||||||
ifeq ($(uname_S),OpenBSD)
|
ifeq ($(uname_S),OpenBSD)
|
||||||
NO_STRCASESTR = YesPlease
|
NO_STRCASESTR = YesPlease
|
||||||
@ -324,6 +347,12 @@ ifdef NEEDS_NSL
|
|||||||
LIBS += -lnsl
|
LIBS += -lnsl
|
||||||
SIMPLE_LIB += -lnsl
|
SIMPLE_LIB += -lnsl
|
||||||
endif
|
endif
|
||||||
|
ifdef NO_D_TYPE_IN_DIRENT
|
||||||
|
ALL_CFLAGS += -DNO_D_TYPE_IN_DIRENT
|
||||||
|
endif
|
||||||
|
ifdef NO_D_INO_IN_DIRENT
|
||||||
|
ALL_CFLAGS += -DNO_D_INO_IN_DIRENT
|
||||||
|
endif
|
||||||
ifdef NO_STRCASESTR
|
ifdef NO_STRCASESTR
|
||||||
COMPAT_CFLAGS += -DNO_STRCASESTR
|
COMPAT_CFLAGS += -DNO_STRCASESTR
|
||||||
COMPAT_OBJS += compat/strcasestr.o
|
COMPAT_OBJS += compat/strcasestr.o
|
||||||
@ -332,12 +361,23 @@ ifdef NO_SETENV
|
|||||||
COMPAT_CFLAGS += -DNO_SETENV
|
COMPAT_CFLAGS += -DNO_SETENV
|
||||||
COMPAT_OBJS += compat/setenv.o
|
COMPAT_OBJS += compat/setenv.o
|
||||||
endif
|
endif
|
||||||
|
ifdef NO_SETENV
|
||||||
|
COMPAT_CFLAGS += -DNO_UNSETENV
|
||||||
|
COMPAT_OBJS += compat/unsetenv.o
|
||||||
|
endif
|
||||||
ifdef NO_MMAP
|
ifdef NO_MMAP
|
||||||
COMPAT_CFLAGS += -DNO_MMAP
|
COMPAT_CFLAGS += -DNO_MMAP
|
||||||
COMPAT_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
|
||||||
|
endif
|
||||||
|
ifdef NO_SOCKADDR_STORAGE
|
||||||
|
ifdef NO_IPV6
|
||||||
|
ALL_CFLAGS += -Dsockaddr_storage=sockaddr_in
|
||||||
|
else
|
||||||
|
ALL_CFLAGS += -Dsockaddr_storage=sockaddr_in6
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef PPC_SHA1
|
ifdef PPC_SHA1
|
||||||
@ -363,13 +403,16 @@ LIB_OBJS += $(COMPAT_OBJS)
|
|||||||
export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
|
export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
|
||||||
### Build rules
|
### Build rules
|
||||||
|
|
||||||
all: $(ALL_PROGRAMS)
|
all: $(ALL_PROGRAMS) git$X gitk
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(MAKE) -C templates
|
$(MAKE) -C templates
|
||||||
|
|
||||||
git$X: git.c $(LIB_FILE) Makefile
|
strip: $(PROGRAMS) git$X
|
||||||
$(CC) -DGIT_EXEC_PATH='"$(bindir)"' -DGIT_VERSION='"$(GIT_VERSION)"' \
|
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
|
||||||
|
|
||||||
|
git$X: git.c $(LIB_FILE)
|
||||||
|
$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
|
||||||
$(CFLAGS) $(COMPAT_CFLAGS) -o $@ $(filter %.c,$^) $(LIB_FILE)
|
$(CFLAGS) $(COMPAT_CFLAGS) -o $@ $(filter %.c,$^) $(LIB_FILE)
|
||||||
|
|
||||||
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
|
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
|
||||||
@ -397,11 +440,26 @@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py
|
|||||||
git-cherry-pick: git-revert
|
git-cherry-pick: git-revert
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
|
git-show: git-whatchanged
|
||||||
|
cp $< $@
|
||||||
|
|
||||||
|
git-status: git-commit
|
||||||
|
cp $< $@
|
||||||
|
|
||||||
|
# These can record GIT_VERSION
|
||||||
|
git$X git.spec \
|
||||||
|
$(patsubst %.sh,%,$(SCRIPT_SH)) \
|
||||||
|
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
|
||||||
|
$(patsubst %.py,%,$(SCRIPT_PYTHON)) \
|
||||||
|
: GIT-VERSION-FILE
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
|
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
|
$(CC) -o $*.o -c $(ALL_CFLAGS) $<
|
||||||
|
|
||||||
|
exec_cmd.o: ALL_CFLAGS += -DGIT_EXEC_PATH=\"$(gitexecdir)\"
|
||||||
|
|
||||||
git-%$X: %.o $(LIB_FILE)
|
git-%$X: %.o $(LIB_FILE)
|
||||||
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
|
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
|
||||||
|
|
||||||
@ -458,7 +516,9 @@ check:
|
|||||||
|
|
||||||
install: all
|
install: all
|
||||||
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(bindir))
|
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(bindir))
|
||||||
$(INSTALL) $(ALL_PROGRAMS) $(call shellquote,$(DESTDIR)$(bindir))
|
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(gitexecdir))
|
||||||
|
$(INSTALL) $(ALL_PROGRAMS) $(call shellquote,$(DESTDIR)$(gitexecdir))
|
||||||
|
$(INSTALL) git$X gitk $(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))
|
||||||
@ -471,7 +531,7 @@ install-doc:
|
|||||||
|
|
||||||
### Maintainer's dist rules
|
### Maintainer's dist rules
|
||||||
|
|
||||||
git.spec: git.spec.in Makefile
|
git.spec: git.spec.in
|
||||||
sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@
|
sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@
|
||||||
|
|
||||||
GIT_TARNAME=git-$(GIT_VERSION)
|
GIT_TARNAME=git-$(GIT_VERSION)
|
||||||
@ -479,31 +539,28 @@ 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.spec $(GIT_TARNAME)
|
@cp git.spec $(GIT_TARNAME)
|
||||||
$(TAR) rf $(GIT_TARNAME).tar $(GIT_TARNAME)/git.spec
|
@echo $(GIT_VERSION) > $(GIT_TARNAME)/version
|
||||||
|
$(TAR) rf $(GIT_TARNAME).tar \
|
||||||
|
$(GIT_TARNAME)/git.spec $(GIT_TARNAME)/version
|
||||||
@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_TARNAME).tar.gz
|
$(RPMBUILD) -ta $(GIT_TARNAME).tar.gz
|
||||||
|
|
||||||
deb: dist
|
|
||||||
rm -rf $(GIT_TARNAME)
|
|
||||||
$(TAR) zxf $(GIT_TARNAME).tar.gz
|
|
||||||
dpkg-source -b $(GIT_TARNAME)
|
|
||||||
cd $(GIT_TARNAME) && fakeroot debian/rules binary
|
|
||||||
|
|
||||||
### Cleaning rules
|
### Cleaning rules
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(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 $(ALL_PROGRAMS) git$X
|
||||||
rm -f $(filter-out gitk,$(SCRIPTS))
|
|
||||||
rm -f *.spec *.pyc *.pyo */*.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-*_$(GIT_VERSION)-*.deb
|
|
||||||
$(MAKE) -C Documentation/ clean
|
$(MAKE) -C Documentation/ clean
|
||||||
$(MAKE) -C templates clean
|
$(MAKE) -C templates clean
|
||||||
$(MAKE) -C t/ clean
|
$(MAKE) -C t/ clean
|
||||||
|
rm -f GIT-VERSION-FILE
|
||||||
|
|
||||||
|
.PHONY: all install clean strip
|
||||||
|
.PHONY: .FORCE-GIT-VERSION-FILE
|
||||||
|
|
||||||
|
36
apply.c
36
apply.c
@ -19,6 +19,7 @@
|
|||||||
static const char *prefix;
|
static const char *prefix;
|
||||||
static int prefix_length = -1;
|
static int prefix_length = -1;
|
||||||
|
|
||||||
|
static int p_value = 1;
|
||||||
static int allow_binary_replacement = 0;
|
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;
|
||||||
@ -31,7 +32,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] [--allow-binary-replacement] [-z] <patch>...";
|
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [-pNUM] <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
|
||||||
@ -217,7 +218,6 @@ static char * find_name(const char *line, char *def, int p_value, int terminate)
|
|||||||
*/
|
*/
|
||||||
static void parse_traditional_patch(const char *first, const char *second, struct patch *patch)
|
static void parse_traditional_patch(const char *first, const char *second, struct patch *patch)
|
||||||
{
|
{
|
||||||
int p_value = 1;
|
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
first += 4; // skip "--- "
|
first += 4; // skip "--- "
|
||||||
@ -1564,31 +1564,13 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
|
|||||||
die("unable to add cache entry for %s", path);
|
die("unable to add cache entry for %s", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_subdirectories(const char *path)
|
|
||||||
{
|
|
||||||
int len = strlen(path);
|
|
||||||
char *buf = xmalloc(len + 1);
|
|
||||||
const char *slash = path;
|
|
||||||
|
|
||||||
while ((slash = strchr(slash+1, '/')) != NULL) {
|
|
||||||
len = slash - path;
|
|
||||||
memcpy(buf, path, len);
|
|
||||||
buf[len] = 0;
|
|
||||||
if (mkdir(buf, 0777) < 0) {
|
|
||||||
if (errno != EEXIST)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
|
static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (S_ISLNK(mode))
|
if (S_ISLNK(mode))
|
||||||
return symlink(buf, path);
|
return symlink(buf, path);
|
||||||
fd = open(path, O_CREAT | O_EXCL | O_WRONLY | O_TRUNC, (mode & 0100) ? 0777 : 0666);
|
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
while (size) {
|
while (size) {
|
||||||
@ -1610,13 +1592,14 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
|
|||||||
* which is true 99% of the time anyway. If they don't,
|
* which is true 99% of the time anyway. If they don't,
|
||||||
* we create them and try again.
|
* we create them and try again.
|
||||||
*/
|
*/
|
||||||
static void create_one_file(const char *path, unsigned mode, const char *buf, unsigned long size)
|
static void create_one_file(char *path, unsigned mode, const char *buf, unsigned long size)
|
||||||
{
|
{
|
||||||
if (!try_create_file(path, mode, buf, size))
|
if (!try_create_file(path, mode, buf, size))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (errno == ENOENT) {
|
if (errno == ENOENT) {
|
||||||
create_subdirectories(path);
|
if (safe_create_leading_directories(path))
|
||||||
|
return;
|
||||||
if (!try_create_file(path, mode, buf, size))
|
if (!try_create_file(path, mode, buf, size))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1635,6 +1618,7 @@ static void create_one_file(const char *path, unsigned mode, const char *buf, un
|
|||||||
}
|
}
|
||||||
if (errno != EEXIST)
|
if (errno != EEXIST)
|
||||||
break;
|
break;
|
||||||
|
++nr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
die("unable to write file %s mode %o", path, mode);
|
die("unable to write file %s mode %o", path, mode);
|
||||||
@ -1642,7 +1626,7 @@ static void create_one_file(const char *path, unsigned mode, const char *buf, un
|
|||||||
|
|
||||||
static void create_file(struct patch *patch)
|
static void create_file(struct patch *patch)
|
||||||
{
|
{
|
||||||
const char *path = patch->new_name;
|
char *path = patch->new_name;
|
||||||
unsigned mode = patch->new_mode;
|
unsigned mode = patch->new_mode;
|
||||||
unsigned long size = patch->resultsize;
|
unsigned long size = patch->resultsize;
|
||||||
char *buf = patch->result;
|
char *buf = patch->result;
|
||||||
@ -1798,6 +1782,10 @@ int main(int argc, char **argv)
|
|||||||
excludes = x;
|
excludes = x;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strncmp(arg, "-p", 2)) {
|
||||||
|
p_value = atoi(arg + 2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "--no-add")) {
|
if (!strcmp(arg, "--no-add")) {
|
||||||
no_add = 1;
|
no_add = 1;
|
||||||
continue;
|
continue;
|
||||||
|
2
blob.c
2
blob.c
@ -1,5 +1,5 @@
|
|||||||
#include "blob.h"
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include "blob.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
const char *blob_type = "blob";
|
const char *blob_type = "blob";
|
||||||
|
25
cache.h
25
cache.h
@ -10,9 +10,13 @@
|
|||||||
#define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
|
#define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DT_UNKNOWN
|
#if defined(DT_UNKNOWN) && !NO_D_TYPE_IN_DIRENT
|
||||||
#define DTYPE(de) ((de)->d_type)
|
#define DTYPE(de) ((de)->d_type)
|
||||||
#else
|
#else
|
||||||
|
#undef DT_UNKNOWN
|
||||||
|
#undef DT_DIR
|
||||||
|
#undef DT_REG
|
||||||
|
#undef DT_LNK
|
||||||
#define DT_UNKNOWN 0
|
#define DT_UNKNOWN 0
|
||||||
#define DT_DIR 1
|
#define DT_DIR 1
|
||||||
#define DT_REG 2
|
#define DT_REG 2
|
||||||
@ -81,7 +85,7 @@ struct cache_entry {
|
|||||||
unsigned int ce_size;
|
unsigned int ce_size;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
unsigned short ce_flags;
|
unsigned short ce_flags;
|
||||||
char name[0];
|
char name[FLEX_ARRAY]; /* more */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CE_NAMEMASK (0x0fff)
|
#define CE_NAMEMASK (0x0fff)
|
||||||
@ -159,6 +163,7 @@ 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 only_use_symrefs;
|
||||||
extern int diff_rename_limit_default;
|
extern int diff_rename_limit_default;
|
||||||
|
extern int shared_repository;
|
||||||
|
|
||||||
#define GIT_REPO_VERSION 0
|
#define GIT_REPO_VERSION 0
|
||||||
extern int repository_format_version;
|
extern int repository_format_version;
|
||||||
@ -183,6 +188,7 @@ extern const unsigned char null_sha1[20];
|
|||||||
|
|
||||||
int git_mkstemp(char *path, size_t n, const char *template);
|
int git_mkstemp(char *path, size_t n, const char *template);
|
||||||
|
|
||||||
|
int adjust_shared_perm(const char *path);
|
||||||
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);
|
char *enter_repo(char *path, int strict);
|
||||||
@ -203,9 +209,6 @@ extern char *write_sha1_file_prepare(void *buf,
|
|||||||
|
|
||||||
extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
|
extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
|
||||||
|
|
||||||
/* Read a tree into the cache */
|
|
||||||
extern int read_tree(void *buffer, unsigned long size, int stage, const char **paths);
|
|
||||||
|
|
||||||
extern int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
|
extern int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
|
||||||
size_t bufsize, size_t *bufposn);
|
size_t bufsize, size_t *bufposn);
|
||||||
extern int write_sha1_to_fd(int fd, const unsigned char *sha1);
|
extern int write_sha1_to_fd(int fd, const unsigned char *sha1);
|
||||||
@ -218,6 +221,9 @@ extern int has_pack_file(const unsigned char *sha1);
|
|||||||
extern int has_pack_index(const unsigned char *sha1);
|
extern int has_pack_index(const unsigned char *sha1);
|
||||||
|
|
||||||
/* Convert to/from hex/sha1 representation */
|
/* Convert to/from hex/sha1 representation */
|
||||||
|
#define MINIMUM_ABBREV 4
|
||||||
|
#define DEFAULT_ABBREV 7
|
||||||
|
|
||||||
extern int get_sha1(const char *str, unsigned char *sha1);
|
extern int get_sha1(const char *str, unsigned char *sha1);
|
||||||
extern int get_sha1_hex(const char *hex, unsigned char *sha1);
|
extern int get_sha1_hex(const char *hex, unsigned char *sha1);
|
||||||
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
|
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
|
||||||
@ -257,7 +263,7 @@ extern int checkout_entry(struct cache_entry *ce, struct checkout *state);
|
|||||||
extern struct alternate_object_database {
|
extern struct alternate_object_database {
|
||||||
struct alternate_object_database *next;
|
struct alternate_object_database *next;
|
||||||
char *name;
|
char *name;
|
||||||
char base[0]; /* more */
|
char base[FLEX_ARRAY]; /* more */
|
||||||
} *alt_odb_list;
|
} *alt_odb_list;
|
||||||
extern void prepare_alt_odb(void);
|
extern void prepare_alt_odb(void);
|
||||||
|
|
||||||
@ -271,7 +277,8 @@ extern struct packed_git {
|
|||||||
unsigned int pack_use_cnt;
|
unsigned int pack_use_cnt;
|
||||||
int pack_local;
|
int pack_local;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
char pack_name[0]; /* something like ".git/objects/pack/xxxxx.pack" */
|
/* something like ".git/objects/pack/xxxxx.pack" */
|
||||||
|
char pack_name[FLEX_ARRAY]; /* more */
|
||||||
} *packed_git;
|
} *packed_git;
|
||||||
|
|
||||||
struct pack_entry {
|
struct pack_entry {
|
||||||
@ -286,7 +293,7 @@ struct ref {
|
|||||||
unsigned char new_sha1[20];
|
unsigned char new_sha1[20];
|
||||||
unsigned char force;
|
unsigned char force;
|
||||||
struct ref *peer_ref; /* when renaming */
|
struct ref *peer_ref; /* when renaming */
|
||||||
char name[0];
|
char name[FLEX_ARRAY]; /* more */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int git_connect(int fd[2], char *url, const char *prog);
|
extern int git_connect(int fd[2], char *url, const char *prog);
|
||||||
@ -341,6 +348,6 @@ extern int copy_fd(int ifd, int ofd);
|
|||||||
|
|
||||||
/* Finish off pack transfer receiving end */
|
/* Finish off pack transfer receiving end */
|
||||||
extern int receive_unpack_pack(int fd[2], const char *me, int quiet);
|
extern int receive_unpack_pack(int fd[2], const char *me, int quiet);
|
||||||
extern int receive_keep_pack(int fd[2], const char *me);
|
extern int receive_keep_pack(int fd[2], const char *me, int quiet);
|
||||||
|
|
||||||
#endif /* CACHE_H */
|
#endif /* CACHE_H */
|
||||||
|
10
clone-pack.c
10
clone-pack.c
@ -6,6 +6,8 @@ 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>]*";
|
||||||
static const char *exec = "git-upload-pack";
|
static const char *exec = "git-upload-pack";
|
||||||
|
|
||||||
|
static int quiet = 0;
|
||||||
|
|
||||||
static void clone_handshake(int fd[2], struct ref *ref)
|
static void clone_handshake(int fd[2], struct ref *ref)
|
||||||
{
|
{
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
@ -123,7 +125,9 @@ static int clone_pack(int fd[2], int nr_match, char **match)
|
|||||||
}
|
}
|
||||||
clone_handshake(fd, refs);
|
clone_handshake(fd, refs);
|
||||||
|
|
||||||
status = receive_keep_pack(fd, "git-clone-pack");
|
status = receive_keep_pack(fd, "git-clone-pack", quiet);
|
||||||
|
if (!quiet)
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
if (!status) {
|
if (!status) {
|
||||||
if (nr_match == 0)
|
if (nr_match == 0)
|
||||||
@ -154,8 +158,10 @@ int main(int argc, char **argv)
|
|||||||
char *arg = argv[i];
|
char *arg = argv[i];
|
||||||
|
|
||||||
if (*arg == '-') {
|
if (*arg == '-') {
|
||||||
if (!strcmp("-q", arg))
|
if (!strcmp("-q", arg)) {
|
||||||
|
quiet = 1;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (!strncmp("--exec=", arg, 7)) {
|
if (!strncmp("--exec=", arg, 7)) {
|
||||||
exec = arg + 7;
|
exec = arg + 7;
|
||||||
continue;
|
continue;
|
||||||
|
920
combine-diff.c
Normal file
920
combine-diff.c
Normal file
@ -0,0 +1,920 @@
|
|||||||
|
#include "cache.h"
|
||||||
|
#include "commit.h"
|
||||||
|
#include "diff.h"
|
||||||
|
#include "diffcore.h"
|
||||||
|
#include "quote.h"
|
||||||
|
|
||||||
|
static int uninteresting(struct diff_filepair *p)
|
||||||
|
{
|
||||||
|
if (diff_unmodified_pair(p))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
|
||||||
|
{
|
||||||
|
struct diff_queue_struct *q = &diff_queued_diff;
|
||||||
|
struct combine_diff_path *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!n) {
|
||||||
|
struct combine_diff_path *list = NULL, **tail = &list;
|
||||||
|
for (i = 0; i < q->nr; i++) {
|
||||||
|
int len;
|
||||||
|
const char *path;
|
||||||
|
if (uninteresting(q->queue[i]))
|
||||||
|
continue;
|
||||||
|
path = q->queue[i]->two->path;
|
||||||
|
len = strlen(path);
|
||||||
|
p = xmalloc(combine_diff_path_size(num_parent, len));
|
||||||
|
p->path = (char*) &(p->parent[num_parent]);
|
||||||
|
memcpy(p->path, path, len);
|
||||||
|
p->path[len] = 0;
|
||||||
|
p->len = len;
|
||||||
|
p->next = NULL;
|
||||||
|
memset(p->parent, 0,
|
||||||
|
sizeof(p->parent[0]) * num_parent);
|
||||||
|
|
||||||
|
memcpy(p->sha1, q->queue[i]->two->sha1, 20);
|
||||||
|
p->mode = q->queue[i]->two->mode;
|
||||||
|
memcpy(p->parent[n].sha1, q->queue[i]->one->sha1, 20);
|
||||||
|
p->parent[n].mode = q->queue[i]->one->mode;
|
||||||
|
p->parent[n].status = q->queue[i]->status;
|
||||||
|
*tail = p;
|
||||||
|
tail = &p->next;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = curr; p; p = p->next) {
|
||||||
|
int found = 0;
|
||||||
|
if (!p->len)
|
||||||
|
continue;
|
||||||
|
for (i = 0; i < q->nr; i++) {
|
||||||
|
const char *path;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (uninteresting(q->queue[i]))
|
||||||
|
continue;
|
||||||
|
path = q->queue[i]->two->path;
|
||||||
|
len = strlen(path);
|
||||||
|
if (len == p->len && !memcmp(path, p->path, len)) {
|
||||||
|
found = 1;
|
||||||
|
memcpy(p->parent[n].sha1,
|
||||||
|
q->queue[i]->one->sha1, 20);
|
||||||
|
p->parent[n].mode = q->queue[i]->one->mode;
|
||||||
|
p->parent[n].status = q->queue[i]->status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
p->len = 0;
|
||||||
|
}
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lines lost from parent */
|
||||||
|
struct lline {
|
||||||
|
struct lline *next;
|
||||||
|
int len;
|
||||||
|
unsigned long parent_map;
|
||||||
|
char line[FLEX_ARRAY];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Lines surviving in the merge result */
|
||||||
|
struct sline {
|
||||||
|
struct lline *lost_head, **lost_tail;
|
||||||
|
char *bol;
|
||||||
|
int len;
|
||||||
|
/* bit 0 up to (N-1) are on if the parent has this line (i.e.
|
||||||
|
* we did not change it).
|
||||||
|
* bit N is used for "interesting" lines, including context.
|
||||||
|
*/
|
||||||
|
unsigned long flag;
|
||||||
|
unsigned long *p_lno;
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *grab_blob(const unsigned char *sha1, unsigned long *size)
|
||||||
|
{
|
||||||
|
char *blob;
|
||||||
|
char type[20];
|
||||||
|
if (!memcmp(sha1, null_sha1, 20)) {
|
||||||
|
/* deleted blob */
|
||||||
|
*size = 0;
|
||||||
|
return xcalloc(1, 1);
|
||||||
|
}
|
||||||
|
blob = read_sha1_file(sha1, type, size);
|
||||||
|
if (strcmp(type, "blob"))
|
||||||
|
die("object '%s' is not a blob!", sha1_to_hex(sha1));
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TMPPATHLEN 50
|
||||||
|
#define MAXLINELEN 10240
|
||||||
|
|
||||||
|
static void write_to_temp_file(char *tmpfile, void *blob, unsigned long size)
|
||||||
|
{
|
||||||
|
int fd = git_mkstemp(tmpfile, TMPPATHLEN, ".diff_XXXXXX");
|
||||||
|
if (fd < 0)
|
||||||
|
die("unable to create temp-file");
|
||||||
|
if (write(fd, blob, size) != size)
|
||||||
|
die("unable to write temp-file");
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_temp_blob(char *tmpfile, const unsigned char *sha1)
|
||||||
|
{
|
||||||
|
unsigned long size;
|
||||||
|
void *blob;
|
||||||
|
blob = grab_blob(sha1, &size);
|
||||||
|
write_to_temp_file(tmpfile, blob, size);
|
||||||
|
free(blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_num(char **cp_p, unsigned int *num_p)
|
||||||
|
{
|
||||||
|
char *cp = *cp_p;
|
||||||
|
unsigned int num = 0;
|
||||||
|
int read_some;
|
||||||
|
|
||||||
|
while ('0' <= *cp && *cp <= '9')
|
||||||
|
num = num * 10 + *cp++ - '0';
|
||||||
|
if (!(read_some = cp - *cp_p))
|
||||||
|
return -1;
|
||||||
|
*cp_p = cp;
|
||||||
|
*num_p = num;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_hunk_header(char *line, int len,
|
||||||
|
unsigned int *ob, unsigned int *on,
|
||||||
|
unsigned int *nb, unsigned int *nn)
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
cp = line + 4;
|
||||||
|
if (parse_num(&cp, ob)) {
|
||||||
|
bad_line:
|
||||||
|
return error("malformed diff output: %s", line);
|
||||||
|
}
|
||||||
|
if (*cp == ',') {
|
||||||
|
cp++;
|
||||||
|
if (parse_num(&cp, on))
|
||||||
|
goto bad_line;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*on = 1;
|
||||||
|
if (*cp++ != ' ' || *cp++ != '+')
|
||||||
|
goto bad_line;
|
||||||
|
if (parse_num(&cp, nb))
|
||||||
|
goto bad_line;
|
||||||
|
if (*cp == ',') {
|
||||||
|
cp++;
|
||||||
|
if (parse_num(&cp, nn))
|
||||||
|
goto bad_line;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*nn = 1;
|
||||||
|
return -!!memcmp(cp, " @@", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void append_lost(struct sline *sline, int n, const char *line)
|
||||||
|
{
|
||||||
|
struct lline *lline;
|
||||||
|
int len = strlen(line);
|
||||||
|
unsigned long this_mask = (1UL<<n);
|
||||||
|
if (line[len-1] == '\n')
|
||||||
|
len--;
|
||||||
|
|
||||||
|
/* Check to see if we can squash things */
|
||||||
|
if (sline->lost_head) {
|
||||||
|
struct lline *last_one = NULL;
|
||||||
|
/* We cannot squash it with earlier one */
|
||||||
|
for (lline = sline->lost_head;
|
||||||
|
lline;
|
||||||
|
lline = lline->next)
|
||||||
|
if (lline->parent_map & this_mask)
|
||||||
|
last_one = lline;
|
||||||
|
lline = last_one ? last_one->next : sline->lost_head;
|
||||||
|
while (lline) {
|
||||||
|
if (lline->len == len &&
|
||||||
|
!memcmp(lline->line, line, len)) {
|
||||||
|
lline->parent_map |= this_mask;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lline = lline->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lline = xmalloc(sizeof(*lline) + len + 1);
|
||||||
|
lline->len = len;
|
||||||
|
lline->next = NULL;
|
||||||
|
lline->parent_map = this_mask;
|
||||||
|
memcpy(lline->line, line, len);
|
||||||
|
lline->line[len] = 0;
|
||||||
|
*sline->lost_tail = lline;
|
||||||
|
sline->lost_tail = &lline->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void combine_diff(const unsigned char *parent, const char *ourtmp,
|
||||||
|
struct sline *sline, int cnt, int n, int num_parent)
|
||||||
|
{
|
||||||
|
FILE *in;
|
||||||
|
char parent_tmp[TMPPATHLEN];
|
||||||
|
char cmd[TMPPATHLEN * 2 + 1024];
|
||||||
|
char line[MAXLINELEN];
|
||||||
|
unsigned int lno, ob, on, nb, nn, p_lno;
|
||||||
|
unsigned long nmask = (1UL << n);
|
||||||
|
struct sline *lost_bucket = NULL;
|
||||||
|
|
||||||
|
if (!cnt)
|
||||||
|
return; /* result deleted */
|
||||||
|
|
||||||
|
write_temp_blob(parent_tmp, parent);
|
||||||
|
sprintf(cmd, "diff --unified=0 -La/x -Lb/x '%s' '%s'",
|
||||||
|
parent_tmp, ourtmp);
|
||||||
|
in = popen(cmd, "r");
|
||||||
|
if (!in)
|
||||||
|
die("cannot spawn %s", cmd);
|
||||||
|
|
||||||
|
lno = 1;
|
||||||
|
while (fgets(line, sizeof(line), in) != NULL) {
|
||||||
|
int len = strlen(line);
|
||||||
|
if (5 < len && !memcmp("@@ -", line, 4)) {
|
||||||
|
if (parse_hunk_header(line, len,
|
||||||
|
&ob, &on, &nb, &nn))
|
||||||
|
break;
|
||||||
|
lno = nb;
|
||||||
|
if (!nb)
|
||||||
|
/* @@ -1,2 +0,0 @@ to remove the
|
||||||
|
* first two lines...
|
||||||
|
*/
|
||||||
|
nb = 1;
|
||||||
|
if (nn == 0)
|
||||||
|
/* @@ -X,Y +N,0 @@ removed Y lines
|
||||||
|
* that would have come *after* line N
|
||||||
|
* in the result. Our lost buckets hang
|
||||||
|
* to the line after the removed lines,
|
||||||
|
*/
|
||||||
|
lost_bucket = &sline[nb];
|
||||||
|
else
|
||||||
|
lost_bucket = &sline[nb-1];
|
||||||
|
if (!sline[nb-1].p_lno)
|
||||||
|
sline[nb-1].p_lno =
|
||||||
|
xcalloc(num_parent,
|
||||||
|
sizeof(unsigned long));
|
||||||
|
sline[nb-1].p_lno[n] = ob;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!lost_bucket)
|
||||||
|
continue; /* not in any hunk yet */
|
||||||
|
switch (line[0]) {
|
||||||
|
case '-':
|
||||||
|
append_lost(lost_bucket, n, line+1);
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
sline[lno-1].flag |= nmask;
|
||||||
|
lno++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(in);
|
||||||
|
unlink(parent_tmp);
|
||||||
|
|
||||||
|
/* Assign line numbers for this parent.
|
||||||
|
*
|
||||||
|
* sline[lno].p_lno[n] records the first line number
|
||||||
|
* (counting from 1) for parent N if the final hunk display
|
||||||
|
* started by showing sline[lno] (possibly showing the lost
|
||||||
|
* lines attached to it first).
|
||||||
|
*/
|
||||||
|
for (lno = 0, p_lno = 1; lno < cnt; lno++) {
|
||||||
|
struct lline *ll;
|
||||||
|
sline[lno].p_lno[n] = p_lno;
|
||||||
|
|
||||||
|
/* How many lines would this sline advance the p_lno? */
|
||||||
|
ll = sline[lno].lost_head;
|
||||||
|
while (ll) {
|
||||||
|
if (ll->parent_map & nmask)
|
||||||
|
p_lno++; /* '-' means parent had it */
|
||||||
|
ll = ll->next;
|
||||||
|
}
|
||||||
|
if (!(sline[lno].flag & nmask))
|
||||||
|
p_lno++; /* no '+' means parent had it */
|
||||||
|
}
|
||||||
|
sline[lno].p_lno[n] = p_lno; /* trailer */
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long context = 3;
|
||||||
|
static char combine_marker = '@';
|
||||||
|
|
||||||
|
static int interesting(struct sline *sline, unsigned long all_mask)
|
||||||
|
{
|
||||||
|
/* If some parents lost lines here, or if we have added to
|
||||||
|
* some parent, it is interesting.
|
||||||
|
*/
|
||||||
|
return ((sline->flag & all_mask) || sline->lost_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long adjust_hunk_tail(struct sline *sline,
|
||||||
|
unsigned long all_mask,
|
||||||
|
unsigned long hunk_begin,
|
||||||
|
unsigned long i)
|
||||||
|
{
|
||||||
|
/* i points at the first uninteresting line. If the last line
|
||||||
|
* of the hunk was interesting only because it has some
|
||||||
|
* deletion, then it is not all that interesting for the
|
||||||
|
* purpose of giving trailing context lines. This is because
|
||||||
|
* we output '-' line and then unmodified sline[i-1] itself in
|
||||||
|
* that case which gives us one extra context line.
|
||||||
|
*/
|
||||||
|
if ((hunk_begin + 1 <= i) && !(sline[i-1].flag & all_mask))
|
||||||
|
i--;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long find_next(struct sline *sline,
|
||||||
|
unsigned long mark,
|
||||||
|
unsigned long i,
|
||||||
|
unsigned long cnt,
|
||||||
|
int uninteresting)
|
||||||
|
{
|
||||||
|
/* We have examined up to i-1 and are about to look at i.
|
||||||
|
* Find next interesting or uninteresting line. Here,
|
||||||
|
* "interesting" does not mean interesting(), but marked by
|
||||||
|
* the give_context() function below (i.e. it includes context
|
||||||
|
* lines that are not interesting to interesting() function
|
||||||
|
* that are surrounded by interesting() ones.
|
||||||
|
*/
|
||||||
|
while (i < cnt)
|
||||||
|
if (uninteresting
|
||||||
|
? !(sline[i].flag & mark)
|
||||||
|
: (sline[i].flag & mark))
|
||||||
|
return i;
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int give_context(struct sline *sline, unsigned long cnt, int num_parent)
|
||||||
|
{
|
||||||
|
unsigned long all_mask = (1UL<<num_parent) - 1;
|
||||||
|
unsigned long mark = (1UL<<num_parent);
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
|
/* Two groups of interesting lines may have a short gap of
|
||||||
|
* unintersting lines. Connect such groups to give them a
|
||||||
|
* bit of context.
|
||||||
|
*
|
||||||
|
* We first start from what the interesting() function says,
|
||||||
|
* and mark them with "mark", and paint context lines with the
|
||||||
|
* mark. So interesting() would still say false for such context
|
||||||
|
* lines but they are treated as "interesting" in the end.
|
||||||
|
*/
|
||||||
|
i = find_next(sline, mark, 0, cnt, 0);
|
||||||
|
if (cnt <= i)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (i < cnt) {
|
||||||
|
unsigned long j = (context < i) ? (i - context) : 0;
|
||||||
|
unsigned long k;
|
||||||
|
|
||||||
|
/* Paint a few lines before the first interesting line. */
|
||||||
|
while (j < i)
|
||||||
|
sline[j++].flag |= mark;
|
||||||
|
|
||||||
|
again:
|
||||||
|
/* we know up to i is to be included. where does the
|
||||||
|
* next uninteresting one start?
|
||||||
|
*/
|
||||||
|
j = find_next(sline, mark, i, cnt, 1);
|
||||||
|
if (cnt <= j)
|
||||||
|
break; /* the rest are all interesting */
|
||||||
|
|
||||||
|
/* lookahead context lines */
|
||||||
|
k = find_next(sline, mark, j, cnt, 0);
|
||||||
|
j = adjust_hunk_tail(sline, all_mask, i, j);
|
||||||
|
|
||||||
|
if (k < j + context) {
|
||||||
|
/* k is interesting and [j,k) are not, but
|
||||||
|
* paint them interesting because the gap is small.
|
||||||
|
*/
|
||||||
|
while (j < k)
|
||||||
|
sline[j++].flag |= mark;
|
||||||
|
i = k;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* j is the first uninteresting line and there is
|
||||||
|
* no overlap beyond it within context lines. Paint
|
||||||
|
* the trailing edge a bit.
|
||||||
|
*/
|
||||||
|
i = k;
|
||||||
|
k = (j + context < cnt) ? j + context : cnt;
|
||||||
|
while (j < k)
|
||||||
|
sline[j++].flag |= mark;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int make_hunks(struct sline *sline, unsigned long cnt,
|
||||||
|
int num_parent, int dense)
|
||||||
|
{
|
||||||
|
unsigned long all_mask = (1UL<<num_parent) - 1;
|
||||||
|
unsigned long mark = (1UL<<num_parent);
|
||||||
|
unsigned long i;
|
||||||
|
int has_interesting = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < cnt; i++) {
|
||||||
|
if (interesting(&sline[i], all_mask))
|
||||||
|
sline[i].flag |= mark;
|
||||||
|
else
|
||||||
|
sline[i].flag &= ~mark;
|
||||||
|
}
|
||||||
|
if (!dense)
|
||||||
|
return give_context(sline, cnt, num_parent);
|
||||||
|
|
||||||
|
/* Look at each hunk, and if we have changes from only one
|
||||||
|
* parent, or the changes are the same from all but one
|
||||||
|
* parent, mark that uninteresting.
|
||||||
|
*/
|
||||||
|
i = 0;
|
||||||
|
while (i < cnt) {
|
||||||
|
unsigned long j, hunk_begin, hunk_end;
|
||||||
|
unsigned long same_diff;
|
||||||
|
while (i < cnt && !(sline[i].flag & mark))
|
||||||
|
i++;
|
||||||
|
if (cnt <= i)
|
||||||
|
break; /* No more interesting hunks */
|
||||||
|
hunk_begin = i;
|
||||||
|
for (j = i + 1; j < cnt; j++) {
|
||||||
|
if (!(sline[j].flag & mark)) {
|
||||||
|
/* Look beyond the end to see if there
|
||||||
|
* is an interesting line after this
|
||||||
|
* hunk within context span.
|
||||||
|
*/
|
||||||
|
unsigned long la; /* lookahead */
|
||||||
|
int contin = 0;
|
||||||
|
la = adjust_hunk_tail(sline, all_mask,
|
||||||
|
hunk_begin, j);
|
||||||
|
la = (la + context < cnt) ?
|
||||||
|
(la + context) : cnt;
|
||||||
|
while (j <= --la) {
|
||||||
|
if (sline[la].flag & mark) {
|
||||||
|
contin = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!contin)
|
||||||
|
break;
|
||||||
|
j = la;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hunk_end = j;
|
||||||
|
|
||||||
|
/* [i..hunk_end) are interesting. Now is it really
|
||||||
|
* interesting? We check if there are only two versions
|
||||||
|
* and the result matches one of them. That is, we look
|
||||||
|
* at:
|
||||||
|
* (+) line, which records lines added to which parents;
|
||||||
|
* this line appears in the result.
|
||||||
|
* (-) line, which records from what parents the line
|
||||||
|
* was removed; this line does not appear in the result.
|
||||||
|
* then check the set of parents the result has difference
|
||||||
|
* from, from all lines. If there are lines that has
|
||||||
|
* different set of parents that the result has differences
|
||||||
|
* from, that means we have more than two versions.
|
||||||
|
*
|
||||||
|
* Even when we have only two versions, if the result does
|
||||||
|
* not match any of the parents, the it should be considered
|
||||||
|
* interesting. In such a case, we would have all '+' line.
|
||||||
|
* After passing the above "two versions" test, that would
|
||||||
|
* appear as "the same set of parents" to be "all parents".
|
||||||
|
*/
|
||||||
|
same_diff = 0;
|
||||||
|
has_interesting = 0;
|
||||||
|
for (j = i; j < hunk_end && !has_interesting; j++) {
|
||||||
|
unsigned long this_diff = sline[j].flag & all_mask;
|
||||||
|
struct lline *ll = sline[j].lost_head;
|
||||||
|
if (this_diff) {
|
||||||
|
/* This has some changes. Is it the
|
||||||
|
* same as others?
|
||||||
|
*/
|
||||||
|
if (!same_diff)
|
||||||
|
same_diff = this_diff;
|
||||||
|
else if (same_diff != this_diff) {
|
||||||
|
has_interesting = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (ll && !has_interesting) {
|
||||||
|
/* Lost this line from these parents;
|
||||||
|
* who are they? Are they the same?
|
||||||
|
*/
|
||||||
|
this_diff = ll->parent_map;
|
||||||
|
if (!same_diff)
|
||||||
|
same_diff = this_diff;
|
||||||
|
else if (same_diff != this_diff) {
|
||||||
|
has_interesting = 1;
|
||||||
|
}
|
||||||
|
ll = ll->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_interesting && same_diff != all_mask) {
|
||||||
|
/* This hunk is not that interesting after all */
|
||||||
|
for (j = hunk_begin; j < hunk_end; j++)
|
||||||
|
sline[j].flag &= ~mark;
|
||||||
|
}
|
||||||
|
i = hunk_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
has_interesting = give_context(sline, cnt, num_parent);
|
||||||
|
return has_interesting;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_parent_lno(struct sline *sline, unsigned long l0, unsigned long l1, unsigned long cnt, int n)
|
||||||
|
{
|
||||||
|
l0 = sline[l0].p_lno[n];
|
||||||
|
l1 = sline[l1].p_lno[n];
|
||||||
|
printf(" -%lu,%lu", l0, l1-l0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
|
||||||
|
{
|
||||||
|
unsigned long mark = (1UL<<num_parent);
|
||||||
|
int i;
|
||||||
|
unsigned long lno = 0;
|
||||||
|
|
||||||
|
if (!cnt)
|
||||||
|
return; /* result deleted */
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
struct sline *sl = &sline[lno];
|
||||||
|
int hunk_end;
|
||||||
|
while (lno < cnt && !(sline[lno].flag & mark))
|
||||||
|
lno++;
|
||||||
|
if (cnt <= lno)
|
||||||
|
break;
|
||||||
|
for (hunk_end = lno + 1; hunk_end < cnt; hunk_end++)
|
||||||
|
if (!(sline[hunk_end].flag & mark))
|
||||||
|
break;
|
||||||
|
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
|
||||||
|
for (i = 0; i < num_parent; i++)
|
||||||
|
show_parent_lno(sline, lno, hunk_end, cnt, i);
|
||||||
|
printf(" +%lu,%lu ", lno+1, hunk_end-lno);
|
||||||
|
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
|
||||||
|
putchar('\n');
|
||||||
|
while (lno < hunk_end) {
|
||||||
|
struct lline *ll;
|
||||||
|
int j;
|
||||||
|
unsigned long p_mask;
|
||||||
|
sl = &sline[lno++];
|
||||||
|
ll = sl->lost_head;
|
||||||
|
while (ll) {
|
||||||
|
for (j = 0; j < num_parent; j++) {
|
||||||
|
if (ll->parent_map & (1UL<<j))
|
||||||
|
putchar('-');
|
||||||
|
else
|
||||||
|
putchar(' ');
|
||||||
|
}
|
||||||
|
puts(ll->line);
|
||||||
|
ll = ll->next;
|
||||||
|
}
|
||||||
|
p_mask = 1;
|
||||||
|
for (j = 0; j < num_parent; j++) {
|
||||||
|
if (p_mask & sl->flag)
|
||||||
|
putchar('+');
|
||||||
|
else
|
||||||
|
putchar(' ');
|
||||||
|
p_mask <<= 1;
|
||||||
|
}
|
||||||
|
printf("%.*s\n", sl->len, sl->bol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reuse_combine_diff(struct sline *sline, unsigned long cnt,
|
||||||
|
int i, int j)
|
||||||
|
{
|
||||||
|
/* We have already examined parent j and we know parent i
|
||||||
|
* and parent j are the same, so reuse the combined result
|
||||||
|
* of parent j for parent i.
|
||||||
|
*/
|
||||||
|
unsigned long lno, imask, jmask;
|
||||||
|
imask = (1UL<<i);
|
||||||
|
jmask = (1UL<<j);
|
||||||
|
|
||||||
|
for (lno = 0; lno < cnt; lno++) {
|
||||||
|
struct lline *ll = sline->lost_head;
|
||||||
|
sline->p_lno[i] = sline->p_lno[j];
|
||||||
|
while (ll) {
|
||||||
|
if (ll->parent_map & jmask)
|
||||||
|
ll->parent_map |= imask;
|
||||||
|
ll = ll->next;
|
||||||
|
}
|
||||||
|
if (sline->flag & jmask)
|
||||||
|
sline->flag |= imask;
|
||||||
|
sline++;
|
||||||
|
}
|
||||||
|
/* the overall size of the file (sline[cnt]) */
|
||||||
|
sline->p_lno[i] = sline->p_lno[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
|
||||||
|
int dense, const char *header)
|
||||||
|
{
|
||||||
|
unsigned long size, cnt, lno;
|
||||||
|
char *result, *cp, *ep;
|
||||||
|
struct sline *sline; /* survived lines */
|
||||||
|
int mode_differs = 0;
|
||||||
|
int i, show_hunks, shown_header = 0;
|
||||||
|
char ourtmp_buf[TMPPATHLEN];
|
||||||
|
char *ourtmp = ourtmp_buf;
|
||||||
|
|
||||||
|
/* Read the result of merge first */
|
||||||
|
if (memcmp(elem->sha1, null_sha1, 20)) {
|
||||||
|
result = grab_blob(elem->sha1, &size);
|
||||||
|
write_to_temp_file(ourtmp, result, size);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Used by diff-tree to read from the working tree */
|
||||||
|
struct stat st;
|
||||||
|
int fd;
|
||||||
|
ourtmp = elem->path;
|
||||||
|
if (0 <= (fd = open(ourtmp, O_RDONLY)) &&
|
||||||
|
!fstat(fd, &st)) {
|
||||||
|
int len = st.st_size;
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
size = len;
|
||||||
|
result = xmalloc(len + 1);
|
||||||
|
while (cnt < len) {
|
||||||
|
int done = xread(fd, result+cnt, len-cnt);
|
||||||
|
if (done == 0)
|
||||||
|
break;
|
||||||
|
if (done < 0)
|
||||||
|
die("read error '%s'", ourtmp);
|
||||||
|
cnt += done;
|
||||||
|
}
|
||||||
|
result[len] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* deleted file */
|
||||||
|
size = 0;
|
||||||
|
result = xmalloc(1);
|
||||||
|
result[0] = 0;
|
||||||
|
ourtmp = "/dev/null";
|
||||||
|
}
|
||||||
|
if (0 <= fd)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cnt = 0, cp = result; cp - result < size; cp++) {
|
||||||
|
if (*cp == '\n')
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
if (size && result[size-1] != '\n')
|
||||||
|
cnt++; /* incomplete line */
|
||||||
|
|
||||||
|
sline = xcalloc(cnt+1, sizeof(*sline));
|
||||||
|
ep = result;
|
||||||
|
sline[0].bol = result;
|
||||||
|
for (lno = 0; lno <= cnt; lno++) {
|
||||||
|
sline[lno].lost_tail = &sline[lno].lost_head;
|
||||||
|
sline[lno].flag = 0;
|
||||||
|
}
|
||||||
|
for (lno = 0, cp = result; cp - result < size; cp++) {
|
||||||
|
if (*cp == '\n') {
|
||||||
|
sline[lno].len = cp - sline[lno].bol;
|
||||||
|
lno++;
|
||||||
|
if (lno < cnt)
|
||||||
|
sline[lno].bol = cp + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (size && result[size-1] != '\n')
|
||||||
|
sline[cnt-1].len = size - (sline[cnt-1].bol - result);
|
||||||
|
|
||||||
|
sline[0].p_lno = xcalloc((cnt+1) * num_parent, sizeof(unsigned long));
|
||||||
|
for (lno = 0; lno < cnt; lno++)
|
||||||
|
sline[lno+1].p_lno = sline[lno].p_lno + num_parent;
|
||||||
|
|
||||||
|
for (i = 0; i < num_parent; i++) {
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
if (!memcmp(elem->parent[i].sha1,
|
||||||
|
elem->parent[j].sha1, 20)) {
|
||||||
|
reuse_combine_diff(sline, cnt, i, j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i <= j)
|
||||||
|
combine_diff(elem->parent[i].sha1, ourtmp, sline,
|
||||||
|
cnt, i, num_parent);
|
||||||
|
if (elem->parent[i].mode != elem->mode)
|
||||||
|
mode_differs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
show_hunks = make_hunks(sline, cnt, num_parent, dense);
|
||||||
|
|
||||||
|
if (show_hunks || mode_differs) {
|
||||||
|
const char *abb;
|
||||||
|
|
||||||
|
if (header) {
|
||||||
|
shown_header++;
|
||||||
|
puts(header);
|
||||||
|
}
|
||||||
|
printf("diff --%s ", dense ? "cc" : "combined");
|
||||||
|
if (quote_c_style(elem->path, NULL, NULL, 0))
|
||||||
|
quote_c_style(elem->path, NULL, stdout, 0);
|
||||||
|
else
|
||||||
|
printf("%s", elem->path);
|
||||||
|
putchar('\n');
|
||||||
|
printf("index ");
|
||||||
|
for (i = 0; i < num_parent; i++) {
|
||||||
|
if (elem->parent[i].mode != elem->mode)
|
||||||
|
mode_differs = 1;
|
||||||
|
abb = find_unique_abbrev(elem->parent[i].sha1,
|
||||||
|
DEFAULT_ABBREV);
|
||||||
|
printf("%s%s", i ? "," : "", abb);
|
||||||
|
}
|
||||||
|
abb = find_unique_abbrev(elem->sha1, DEFAULT_ABBREV);
|
||||||
|
printf("..%s\n", abb);
|
||||||
|
|
||||||
|
if (mode_differs) {
|
||||||
|
int added = !!elem->mode;
|
||||||
|
for (i = 0; added && i < num_parent; i++)
|
||||||
|
if (elem->parent[i].status !=
|
||||||
|
DIFF_STATUS_ADDED)
|
||||||
|
added = 0;
|
||||||
|
if (added)
|
||||||
|
printf("new file mode %06o", elem->mode);
|
||||||
|
else {
|
||||||
|
if (!elem->mode)
|
||||||
|
printf("deleted file ");
|
||||||
|
printf("mode ");
|
||||||
|
for (i = 0; i < num_parent; i++) {
|
||||||
|
printf("%s%06o", i ? "," : "",
|
||||||
|
elem->parent[i].mode);
|
||||||
|
}
|
||||||
|
if (elem->mode)
|
||||||
|
printf("..%06o", elem->mode);
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
dump_sline(sline, cnt, num_parent);
|
||||||
|
}
|
||||||
|
if (ourtmp == ourtmp_buf)
|
||||||
|
unlink(ourtmp);
|
||||||
|
free(result);
|
||||||
|
|
||||||
|
for (i = 0; i < cnt; i++) {
|
||||||
|
if (sline[i].lost_head) {
|
||||||
|
struct lline *ll = sline[i].lost_head;
|
||||||
|
while (ll) {
|
||||||
|
struct lline *tmp = ll;
|
||||||
|
ll = ll->next;
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(sline[0].p_lno);
|
||||||
|
free(sline);
|
||||||
|
return shown_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define COLONS "::::::::::::::::::::::::::::::::"
|
||||||
|
|
||||||
|
static void show_raw_diff(struct combine_diff_path *p, int num_parent, const char *header, struct diff_options *opt)
|
||||||
|
{
|
||||||
|
int i, offset, mod_type = 'A';
|
||||||
|
const char *prefix;
|
||||||
|
int line_termination, inter_name_termination;
|
||||||
|
|
||||||
|
line_termination = opt->line_termination;
|
||||||
|
inter_name_termination = '\t';
|
||||||
|
if (!line_termination)
|
||||||
|
inter_name_termination = 0;
|
||||||
|
|
||||||
|
if (header)
|
||||||
|
puts(header);
|
||||||
|
|
||||||
|
for (i = 0; i < num_parent; i++) {
|
||||||
|
if (p->parent[i].mode)
|
||||||
|
mod_type = 'M';
|
||||||
|
}
|
||||||
|
if (!p->mode)
|
||||||
|
mod_type = 'D';
|
||||||
|
|
||||||
|
if (opt->output_format == DIFF_FORMAT_RAW) {
|
||||||
|
offset = strlen(COLONS) - num_parent;
|
||||||
|
if (offset < 0)
|
||||||
|
offset = 0;
|
||||||
|
prefix = COLONS + offset;
|
||||||
|
|
||||||
|
/* Show the modes */
|
||||||
|
for (i = 0; i < num_parent; i++) {
|
||||||
|
printf("%s%06o", prefix, p->parent[i].mode);
|
||||||
|
prefix = " ";
|
||||||
|
}
|
||||||
|
printf("%s%06o", prefix, p->mode);
|
||||||
|
|
||||||
|
/* Show sha1's */
|
||||||
|
for (i = 0; i < num_parent; i++)
|
||||||
|
printf(" %s", diff_unique_abbrev(p->parent[i].sha1,
|
||||||
|
opt->abbrev));
|
||||||
|
printf(" %s ", diff_unique_abbrev(p->sha1, opt->abbrev));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt->output_format == DIFF_FORMAT_RAW ||
|
||||||
|
opt->output_format == DIFF_FORMAT_NAME_STATUS) {
|
||||||
|
for (i = 0; i < num_parent; i++)
|
||||||
|
putchar(p->parent[i].status);
|
||||||
|
putchar(inter_name_termination);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_termination) {
|
||||||
|
if (quote_c_style(p->path, NULL, NULL, 0))
|
||||||
|
quote_c_style(p->path, NULL, stdout, 0);
|
||||||
|
else
|
||||||
|
printf("%s", p->path);
|
||||||
|
putchar(line_termination);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("%s%c", p->path, line_termination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int show_combined_diff(struct combine_diff_path *p,
|
||||||
|
int num_parent,
|
||||||
|
int dense,
|
||||||
|
const char *header,
|
||||||
|
struct diff_options *opt)
|
||||||
|
{
|
||||||
|
if (!p->len)
|
||||||
|
return 0;
|
||||||
|
switch (opt->output_format) {
|
||||||
|
case DIFF_FORMAT_RAW:
|
||||||
|
case DIFF_FORMAT_NAME_STATUS:
|
||||||
|
case DIFF_FORMAT_NAME:
|
||||||
|
show_raw_diff(p, num_parent, header, opt);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
case DIFF_FORMAT_PATCH:
|
||||||
|
return show_patch_diff(p, num_parent, dense, header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *diff_tree_combined_merge(const unsigned char *sha1,
|
||||||
|
const char *header, int dense,
|
||||||
|
struct diff_options *opt)
|
||||||
|
{
|
||||||
|
struct commit *commit = lookup_commit(sha1);
|
||||||
|
struct diff_options diffopts;
|
||||||
|
struct commit_list *parents;
|
||||||
|
struct combine_diff_path *p, *paths = NULL;
|
||||||
|
int num_parent, i, num_paths;
|
||||||
|
|
||||||
|
diffopts = *opt;
|
||||||
|
diffopts.output_format = DIFF_FORMAT_NO_OUTPUT;
|
||||||
|
diffopts.recursive = 1;
|
||||||
|
|
||||||
|
/* count parents */
|
||||||
|
for (parents = commit->parents, num_parent = 0;
|
||||||
|
parents;
|
||||||
|
parents = parents->next, num_parent++)
|
||||||
|
; /* nothing */
|
||||||
|
|
||||||
|
/* find set of paths that everybody touches */
|
||||||
|
for (parents = commit->parents, i = 0;
|
||||||
|
parents;
|
||||||
|
parents = parents->next, i++) {
|
||||||
|
struct commit *parent = parents->item;
|
||||||
|
diff_tree_sha1(parent->object.sha1, commit->object.sha1, "",
|
||||||
|
&diffopts);
|
||||||
|
diffcore_std(&diffopts);
|
||||||
|
paths = intersect_paths(paths, i, num_parent);
|
||||||
|
diff_flush(&diffopts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find out surviving paths */
|
||||||
|
for (num_paths = 0, p = paths; p; p = p->next) {
|
||||||
|
if (p->len)
|
||||||
|
num_paths++;
|
||||||
|
}
|
||||||
|
if (num_paths) {
|
||||||
|
for (p = paths; p; p = p->next) {
|
||||||
|
if (show_combined_diff(p, num_parent, dense,
|
||||||
|
header, opt))
|
||||||
|
header = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean things up */
|
||||||
|
while (paths) {
|
||||||
|
struct combine_diff_path *tmp = paths;
|
||||||
|
paths = paths->next;
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
return header;
|
||||||
|
}
|
@ -86,13 +86,13 @@ int main(int argc, char **argv)
|
|||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
|
||||||
setup_ident();
|
setup_ident();
|
||||||
|
setup_git_directory();
|
||||||
|
|
||||||
git_config(git_default_config);
|
git_config(git_default_config);
|
||||||
|
|
||||||
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;
|
||||||
|
66
commit.c
66
commit.c
@ -1,6 +1,6 @@
|
|||||||
|
#include "cache.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "cache.h"
|
|
||||||
|
|
||||||
int save_commit_buffer = 1;
|
int save_commit_buffer = 1;
|
||||||
|
|
||||||
@ -352,6 +352,21 @@ struct commit *pop_most_recent_commit(struct commit_list **list,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear_commit_marks(struct commit *commit, unsigned int mark)
|
||||||
|
{
|
||||||
|
struct commit_list *parents;
|
||||||
|
|
||||||
|
parents = commit->parents;
|
||||||
|
commit->object.flags &= ~mark;
|
||||||
|
while (parents) {
|
||||||
|
struct commit *parent = parents->item;
|
||||||
|
if (parent && parent->object.parsed &&
|
||||||
|
(parent->object.flags & mark))
|
||||||
|
clear_commit_marks(parent, mark);
|
||||||
|
parents = parents->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic support for pretty-printing the header
|
* Generic support for pretty-printing the header
|
||||||
*/
|
*/
|
||||||
@ -411,33 +426,37 @@ static int is_empty_line(const char *line, int len)
|
|||||||
return !len;
|
return !len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_parent_info(enum cmit_fmt fmt, char *buf, const char *line, int parents)
|
static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *commit, int abbrev)
|
||||||
{
|
{
|
||||||
int offset = 0;
|
struct commit_list *parent = commit->parents;
|
||||||
|
int offset;
|
||||||
|
|
||||||
if (fmt == CMIT_FMT_ONELINE)
|
if ((fmt == CMIT_FMT_ONELINE) || !parent || !parent->next)
|
||||||
return offset;
|
return 0;
|
||||||
switch (parents) {
|
|
||||||
case 1:
|
offset = sprintf(buf, "Merge:");
|
||||||
break;
|
|
||||||
case 2:
|
while (parent) {
|
||||||
/* Go back to the previous line: 40 characters of previous parent, and one '\n' */
|
struct commit *p = parent->item;
|
||||||
offset = sprintf(buf, "Merge: %.40s\n", line-41);
|
const char *hex = abbrev
|
||||||
/* Fallthrough */
|
? find_unique_abbrev(p->object.sha1, abbrev)
|
||||||
default:
|
: sha1_to_hex(p->object.sha1);
|
||||||
/* Replace the previous '\n' with a space */
|
char *dots = (abbrev && strlen(hex) != 40) ? "..." : "";
|
||||||
buf[offset-1] = ' ';
|
parent = parent->next;
|
||||||
offset += sprintf(buf + offset, "%.40s\n", line+7);
|
|
||||||
|
offset += sprintf(buf + offset, " %s%s", hex, dots);
|
||||||
}
|
}
|
||||||
|
buf[offset++] = '\n';
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg, unsigned long len, char *buf, unsigned long space)
|
unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, unsigned long len, char *buf, unsigned long space, int abbrev)
|
||||||
{
|
{
|
||||||
int hdr = 1, body = 0;
|
int hdr = 1, body = 0;
|
||||||
unsigned long offset = 0;
|
unsigned long offset = 0;
|
||||||
int parents = 0;
|
|
||||||
int indent = (fmt == CMIT_FMT_ONELINE) ? 0 : 4;
|
int indent = (fmt == CMIT_FMT_ONELINE) ? 0 : 4;
|
||||||
|
int parents_shown = 0;
|
||||||
|
const char *msg = commit->buffer;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const char *line = msg;
|
const char *line = msg;
|
||||||
@ -473,9 +492,15 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg, unsigned l
|
|||||||
if (!memcmp(line, "parent ", 7)) {
|
if (!memcmp(line, "parent ", 7)) {
|
||||||
if (linelen != 48)
|
if (linelen != 48)
|
||||||
die("bad parent line in commit");
|
die("bad parent line in commit");
|
||||||
offset += add_parent_info(fmt, buf + offset, line, ++parents);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!parents_shown) {
|
||||||
|
offset += add_merge_info(fmt, buf + offset,
|
||||||
|
commit, abbrev);
|
||||||
|
parents_shown = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* MEDIUM == DEFAULT shows only author with dates.
|
* MEDIUM == DEFAULT shows only author with dates.
|
||||||
* FULL shows both authors but not dates.
|
* FULL shows both authors but not dates.
|
||||||
@ -560,6 +585,9 @@ void sort_in_topological_order(struct commit_list ** list)
|
|||||||
next = next->next;
|
next = next->next;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!count)
|
||||||
|
return;
|
||||||
/* allocate an array to help sort the list */
|
/* allocate an array to help sort the list */
|
||||||
nodes = xcalloc(count, sizeof(*nodes));
|
nodes = xcalloc(count, sizeof(*nodes));
|
||||||
/* link the list to the array */
|
/* link the list to the array */
|
||||||
|
4
commit.h
4
commit.h
@ -48,7 +48,7 @@ enum cmit_fmt {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern enum cmit_fmt get_commit_format(const char *arg);
|
extern enum cmit_fmt get_commit_format(const char *arg);
|
||||||
extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg, unsigned long len, char *buf, unsigned long space);
|
extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char *buf, unsigned long space, int abbrev);
|
||||||
|
|
||||||
/** Removes the first commit from a list sorted by date, and adds all
|
/** Removes the first commit from a list sorted by date, and adds all
|
||||||
* of its parents.
|
* of its parents.
|
||||||
@ -58,6 +58,8 @@ struct commit *pop_most_recent_commit(struct commit_list **list,
|
|||||||
|
|
||||||
struct commit *pop_commit(struct commit_list **stack);
|
struct commit *pop_commit(struct commit_list **stack);
|
||||||
|
|
||||||
|
void clear_commit_marks(struct commit *commit, unsigned int mark);
|
||||||
|
|
||||||
int count_parents(struct commit * commit);
|
int count_parents(struct commit * commit);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
26
compat/unsetenv.c
Normal file
26
compat/unsetenv.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void gitunsetenv (const char *name)
|
||||||
|
{
|
||||||
|
extern char **environ;
|
||||||
|
int src, dst;
|
||||||
|
size_t nmln;
|
||||||
|
|
||||||
|
nmln = strlen(name);
|
||||||
|
|
||||||
|
for (src = dst = 0; environ[src]; ++src) {
|
||||||
|
size_t enln;
|
||||||
|
enln = strlen(environ[src]);
|
||||||
|
if (enln > nmln) {
|
||||||
|
/* might match, and can test for '=' safely */
|
||||||
|
if (0 == strncmp (environ[src], name, nmln)
|
||||||
|
&& '=' == environ[src][nmln])
|
||||||
|
/* matches, so skip */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
environ[dst] = environ[src];
|
||||||
|
++dst;
|
||||||
|
}
|
||||||
|
environ[dst] = NULL;
|
||||||
|
}
|
19
config.c
19
config.c
@ -409,8 +409,7 @@ int git_config_set_multivar(const char* key, const char* value,
|
|||||||
const char* value_regex, int multi_replace)
|
const char* value_regex, int multi_replace)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct stat st;
|
int fd, in_fd;
|
||||||
int fd;
|
|
||||||
char* config_filename = strdup(git_path("config"));
|
char* config_filename = strdup(git_path("config"));
|
||||||
char* lock_file = strdup(git_path("config.lock"));
|
char* lock_file = strdup(git_path("config.lock"));
|
||||||
const char* last_dot = strrchr(key, '.');
|
const char* last_dot = strrchr(key, '.');
|
||||||
@ -457,9 +456,17 @@ int git_config_set_multivar(const char* key, const char* value,
|
|||||||
/*
|
/*
|
||||||
* If .git/config does not exist yet, write a minimal version.
|
* If .git/config does not exist yet, write a minimal version.
|
||||||
*/
|
*/
|
||||||
if (stat(config_filename, &st)) {
|
in_fd = open(config_filename, O_RDONLY);
|
||||||
|
if ( in_fd < 0 ) {
|
||||||
free(store.key);
|
free(store.key);
|
||||||
|
|
||||||
|
if ( ENOENT != errno ) {
|
||||||
|
error("opening %s: %s", config_filename,
|
||||||
|
strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
unlink(lock_file);
|
||||||
|
return 3; /* same as "invalid config file" */
|
||||||
|
}
|
||||||
/* if nothing to unset, error out */
|
/* if nothing to unset, error out */
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -471,7 +478,7 @@ int git_config_set_multivar(const char* key, const char* value,
|
|||||||
store_write_section(fd, key);
|
store_write_section(fd, key);
|
||||||
store_write_pair(fd, key, value);
|
store_write_pair(fd, key, value);
|
||||||
} else{
|
} else{
|
||||||
int in_fd;
|
struct stat st;
|
||||||
char* contents;
|
char* contents;
|
||||||
int i, copy_begin, copy_end, new_line = 0;
|
int i, copy_begin, copy_end, new_line = 0;
|
||||||
|
|
||||||
@ -487,7 +494,7 @@ int git_config_set_multivar(const char* key, const char* value,
|
|||||||
store.value_regex = (regex_t*)malloc(sizeof(regex_t));
|
store.value_regex = (regex_t*)malloc(sizeof(regex_t));
|
||||||
if (regcomp(store.value_regex, value_regex,
|
if (regcomp(store.value_regex, value_regex,
|
||||||
REG_EXTENDED)) {
|
REG_EXTENDED)) {
|
||||||
fprintf(stderr, "Invalid pattern: %s",
|
fprintf(stderr, "Invalid pattern: %s\n",
|
||||||
value_regex);
|
value_regex);
|
||||||
free(store.value_regex);
|
free(store.value_regex);
|
||||||
return 6;
|
return 6;
|
||||||
@ -528,7 +535,7 @@ int git_config_set_multivar(const char* key, const char* value,
|
|||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
in_fd = open(config_filename, O_RDONLY, 0666);
|
fstat(in_fd, &st);
|
||||||
contents = mmap(NULL, st.st_size, PROT_READ,
|
contents = mmap(NULL, st.st_size, PROT_READ,
|
||||||
MAP_PRIVATE, in_fd, 0);
|
MAP_PRIVATE, in_fd, 0);
|
||||||
close(in_fd);
|
close(in_fd);
|
||||||
|
49
connect.c
49
connect.c
@ -1,3 +1,4 @@
|
|||||||
|
#include "git-compat-util.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "pkt-line.h"
|
#include "pkt-line.h"
|
||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
@ -34,10 +35,6 @@ struct ref **get_remote_heads(int in, struct ref **list,
|
|||||||
die("protocol error: expected sha/ref, got '%s'", buffer);
|
die("protocol error: expected sha/ref, got '%s'", buffer);
|
||||||
name = buffer + 41;
|
name = buffer + 41;
|
||||||
|
|
||||||
if (ignore_funny && 45 < len && !memcmp(name, "refs/", 5) &&
|
|
||||||
check_ref_format(name + 5))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
name_len = strlen(name);
|
name_len = strlen(name);
|
||||||
if (len != name_len + 41) {
|
if (len != name_len + 41) {
|
||||||
if (server_capabilities)
|
if (server_capabilities)
|
||||||
@ -45,6 +42,10 @@ struct ref **get_remote_heads(int in, struct ref **list,
|
|||||||
server_capabilities = strdup(name + name_len + 1);
|
server_capabilities = strdup(name + name_len + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ignore_funny && 45 < len && !memcmp(name, "refs/", 5) &&
|
||||||
|
check_ref_format(name + 5))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (nr_match && !path_match(name, nr_match, match))
|
if (nr_match && !path_match(name, nr_match, match))
|
||||||
continue;
|
continue;
|
||||||
ref = xcalloc(1, sizeof(*ref) + len - 40);
|
ref = xcalloc(1, sizeof(*ref) + len - 40);
|
||||||
@ -561,7 +562,8 @@ int git_connect(int fd[2], char *url, const char *prog)
|
|||||||
{
|
{
|
||||||
char command[1024];
|
char command[1024];
|
||||||
char *host, *path = url;
|
char *host, *path = url;
|
||||||
char *colon = NULL;
|
char *end;
|
||||||
|
int c;
|
||||||
int pipefd[2][2];
|
int pipefd[2][2];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
enum protocol protocol = PROTO_LOCAL;
|
enum protocol protocol = PROTO_LOCAL;
|
||||||
@ -571,15 +573,30 @@ int git_connect(int fd[2], char *url, const char *prog)
|
|||||||
*host = '\0';
|
*host = '\0';
|
||||||
protocol = get_protocol(url);
|
protocol = get_protocol(url);
|
||||||
host += 3;
|
host += 3;
|
||||||
path = strchr(host, '/');
|
c = '/';
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
host = url;
|
host = url;
|
||||||
if ((colon = strchr(host, ':'))) {
|
c = ':';
|
||||||
protocol = PROTO_SSH;
|
|
||||||
*colon = '\0';
|
|
||||||
path = colon + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (host[0] == '[') {
|
||||||
|
end = strchr(host + 1, ']');
|
||||||
|
if (end) {
|
||||||
|
*end = 0;
|
||||||
|
end++;
|
||||||
|
host++;
|
||||||
|
} else
|
||||||
|
end = host;
|
||||||
|
} else
|
||||||
|
end = host;
|
||||||
|
|
||||||
|
path = strchr(end, c);
|
||||||
|
if (c == ':') {
|
||||||
|
if (path) {
|
||||||
|
protocol = PROTO_SSH;
|
||||||
|
*path++ = '\0';
|
||||||
|
} else
|
||||||
|
path = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!path || !*path)
|
if (!path || !*path)
|
||||||
@ -628,8 +645,14 @@ int git_connect(int fd[2], char *url, const char *prog)
|
|||||||
ssh_basename++;
|
ssh_basename++;
|
||||||
execlp(ssh, ssh_basename, host, command, NULL);
|
execlp(ssh, ssh_basename, host, command, NULL);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
unsetenv(ALTERNATE_DB_ENVIRONMENT);
|
||||||
|
unsetenv(DB_ENVIRONMENT);
|
||||||
|
unsetenv(GIT_DIR_ENVIRONMENT);
|
||||||
|
unsetenv(GRAFT_ENVIRONMENT);
|
||||||
|
unsetenv(INDEX_ENVIRONMENT);
|
||||||
execlp("sh", "sh", "-c", command, NULL);
|
execlp("sh", "sh", "-c", command, NULL);
|
||||||
|
}
|
||||||
die("exec failed");
|
die("exec failed");
|
||||||
}
|
}
|
||||||
fd[0] = pipefd[0][0];
|
fd[0] = pipefd[0][0];
|
||||||
|
7
copy.c
7
copy.c
@ -22,13 +22,16 @@ int copy_fd(int ifd, int ofd)
|
|||||||
buf += written;
|
buf += written;
|
||||||
len -= written;
|
len -= written;
|
||||||
}
|
}
|
||||||
else if (!written)
|
else if (!written) {
|
||||||
|
close(ifd);
|
||||||
return error("copy-fd: write returned 0");
|
return error("copy-fd: write returned 0");
|
||||||
else
|
} else {
|
||||||
|
close(ifd);
|
||||||
return error("copy-fd: write returned %s",
|
return error("copy-fd: write returned %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
close(ifd);
|
close(ifd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,7 @@
|
|||||||
*
|
*
|
||||||
* Number of bytes that are _not_ copied from the source is deletion,
|
* Number of bytes that are _not_ copied from the source is deletion,
|
||||||
* and number of inserted literal bytes are addition, so sum of them
|
* and number of inserted literal bytes are addition, so sum of them
|
||||||
* is the extent of damage. xdelta can express an edit that copies
|
* is the extent of damage.
|
||||||
* data inside of the destination which originally came from the
|
|
||||||
* source. We do not count that in the following routine, so we are
|
|
||||||
* undercounting the source material that remains in the final output
|
|
||||||
* that way.
|
|
||||||
*/
|
*/
|
||||||
int count_delta(void *delta_buf, unsigned long delta_size,
|
int count_delta(void *delta_buf, unsigned long delta_size,
|
||||||
unsigned long *src_copied, unsigned long *literal_added)
|
unsigned long *src_copied, unsigned long *literal_added)
|
||||||
@ -50,12 +46,9 @@ int count_delta(void *delta_buf, unsigned long delta_size,
|
|||||||
if (cmd & 0x08) cp_off |= (*data++ << 24);
|
if (cmd & 0x08) cp_off |= (*data++ << 24);
|
||||||
if (cmd & 0x10) cp_size = *data++;
|
if (cmd & 0x10) cp_size = *data++;
|
||||||
if (cmd & 0x20) cp_size |= (*data++ << 8);
|
if (cmd & 0x20) cp_size |= (*data++ << 8);
|
||||||
|
if (cmd & 0x40) cp_size |= (*data++ << 16);
|
||||||
if (cp_size == 0) cp_size = 0x10000;
|
if (cp_size == 0) cp_size = 0x10000;
|
||||||
|
|
||||||
if (cmd & 0x40)
|
|
||||||
/* copy from dst */
|
|
||||||
;
|
|
||||||
else
|
|
||||||
copied_from_source += cp_size;
|
copied_from_source += cp_size;
|
||||||
out += cp_size;
|
out += cp_size;
|
||||||
} else {
|
} else {
|
||||||
|
88
daemon.c
88
daemon.c
@ -9,13 +9,17 @@
|
|||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include "pkt-line.h"
|
#include "pkt-line.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include "exec_cmd.h"
|
||||||
|
|
||||||
static int log_syslog;
|
static int log_syslog;
|
||||||
static int verbose;
|
static int verbose;
|
||||||
|
static int reuseaddr;
|
||||||
|
|
||||||
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] [--strict-paths] [directory...]";
|
" [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
|
||||||
|
" [--base-path=path] [--user-path | --user-path=path]\n"
|
||||||
|
" [--reuseaddr] [directory...]";
|
||||||
|
|
||||||
/* List of acceptable pathname prefixes */
|
/* List of acceptable pathname prefixes */
|
||||||
static char **ok_paths = NULL;
|
static char **ok_paths = NULL;
|
||||||
@ -24,6 +28,15 @@ 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;
|
||||||
|
|
||||||
|
/* Take all paths relative to this one if non-NULL */
|
||||||
|
static char *base_path = NULL;
|
||||||
|
|
||||||
|
/* If defined, ~user notation is allowed and the string is inserted
|
||||||
|
* after ~user/. E.g. a request to git://host/~alice/frotz would
|
||||||
|
* go to /home/alice/pub_git/frotz with --user-path=pub_git.
|
||||||
|
*/
|
||||||
|
static char *user_path = NULL;
|
||||||
|
|
||||||
/* Timeout, and initial timeout */
|
/* Timeout, and initial timeout */
|
||||||
static unsigned int timeout = 0;
|
static unsigned int timeout = 0;
|
||||||
static unsigned int init_timeout = 0;
|
static unsigned int init_timeout = 0;
|
||||||
@ -131,6 +144,7 @@ static int avoid_alias(char *p)
|
|||||||
|
|
||||||
static char *path_ok(char *dir)
|
static char *path_ok(char *dir)
|
||||||
{
|
{
|
||||||
|
static char rpath[PATH_MAX];
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
if (avoid_alias(dir)) {
|
if (avoid_alias(dir)) {
|
||||||
@ -138,6 +152,40 @@ static char *path_ok(char *dir)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*dir == '~') {
|
||||||
|
if (!user_path) {
|
||||||
|
logerror("'%s': User-path not allowed", dir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (*user_path) {
|
||||||
|
/* Got either "~alice" or "~alice/foo";
|
||||||
|
* rewrite them to "~alice/%s" or
|
||||||
|
* "~alice/%s/foo".
|
||||||
|
*/
|
||||||
|
int namlen, restlen = strlen(dir);
|
||||||
|
char *slash = strchr(dir, '/');
|
||||||
|
if (!slash)
|
||||||
|
slash = dir + restlen;
|
||||||
|
namlen = slash - dir;
|
||||||
|
restlen -= namlen;
|
||||||
|
loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash);
|
||||||
|
snprintf(rpath, PATH_MAX, "%.*s/%s%.*s",
|
||||||
|
namlen, dir, user_path, restlen, slash);
|
||||||
|
dir = rpath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (base_path) {
|
||||||
|
if (*dir != '/') {
|
||||||
|
/* Allow only absolute */
|
||||||
|
logerror("'%s': Non-absolute path denied (base-path active)", dir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snprintf(rpath, PATH_MAX, "%s%s", base_path, dir);
|
||||||
|
dir = rpath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
path = enter_repo(dir, strict_paths);
|
path = enter_repo(dir, strict_paths);
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
@ -212,7 +260,7 @@ static int upload(char *dir)
|
|||||||
snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
|
snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
|
||||||
|
|
||||||
/* git-upload-pack only ever reads stuff, so this is safe */
|
/* git-upload-pack only ever reads stuff, so this is safe */
|
||||||
execlp("git-upload-pack", "git-upload-pack", "--strict", timeout_buf, ".", NULL);
|
execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,6 +479,16 @@ static void child_handler(int signo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_reuse_addr(int sockfd)
|
||||||
|
{
|
||||||
|
int on = 1;
|
||||||
|
|
||||||
|
if (!reuseaddr)
|
||||||
|
return 0;
|
||||||
|
return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
&on, sizeof(on));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NO_IPV6
|
#ifndef NO_IPV6
|
||||||
|
|
||||||
static int socksetup(int port, int **socklist_p)
|
static int socksetup(int port, int **socklist_p)
|
||||||
@ -475,6 +533,11 @@ static int socksetup(int port, int **socklist_p)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (set_reuse_addr(sockfd)) {
|
||||||
|
close(sockfd);
|
||||||
|
return 0; /* not fatal */
|
||||||
|
}
|
||||||
|
|
||||||
if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
|
if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
continue; /* not fatal */
|
continue; /* not fatal */
|
||||||
@ -517,6 +580,11 @@ static int socksetup(int port, int **socklist_p)
|
|||||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
sin.sin_port = htons(port);
|
sin.sin_port = htons(port);
|
||||||
|
|
||||||
|
if (set_reuse_addr(sockfd)) {
|
||||||
|
close(sockfd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
|
if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
return 0;
|
return 0;
|
||||||
@ -639,6 +707,22 @@ int main(int argc, char **argv)
|
|||||||
strict_paths = 1;
|
strict_paths = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strncmp(arg, "--base-path=", 12)) {
|
||||||
|
base_path = arg+12;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(arg, "--reuseaddr")) {
|
||||||
|
reuseaddr = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(arg, "--user-path")) {
|
||||||
|
user_path = "";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strncmp(arg, "--user-path=", 12)) {
|
||||||
|
user_path = arg + 12;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "--")) {
|
if (!strcmp(arg, "--")) {
|
||||||
ok_paths = &argv[i+1];
|
ok_paths = &argv[i+1];
|
||||||
break;
|
break;
|
||||||
|
4
date.c
4
date.c
@ -326,7 +326,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE! We will give precedence to day-of-month over month or
|
* NOTE! We will give precedence to day-of-month over month or
|
||||||
* year numebers in the 1-12 range. So 05 is always "mday 5",
|
* year numbers in the 1-12 range. So 05 is always "mday 5",
|
||||||
* unless we already have a mday..
|
* unless we already have a mday..
|
||||||
*
|
*
|
||||||
* IOW, 01 Apr 05 parses as "April 1st, 2005".
|
* IOW, 01 Apr 05 parses as "April 1st, 2005".
|
||||||
@ -640,7 +640,7 @@ unsigned long approxidate(const char *date)
|
|||||||
}
|
}
|
||||||
if (number > 0 && number < 32)
|
if (number > 0 && number < 32)
|
||||||
tm.tm_mday = number;
|
tm.tm_mday = number;
|
||||||
if (tm.tm_mon > now.tm_mon)
|
if (tm.tm_mon > now.tm_mon && tm.tm_year == now.tm_year)
|
||||||
tm.tm_year--;
|
tm.tm_year--;
|
||||||
return mktime(&tm);
|
return mktime(&tm);
|
||||||
}
|
}
|
||||||
|
6
debian/.gitignore
vendored
6
debian/.gitignore
vendored
@ -1,6 +0,0 @@
|
|||||||
git-core
|
|
||||||
git-tk
|
|
||||||
*.debhelper
|
|
||||||
*.substvars
|
|
||||||
build-stamp
|
|
||||||
files
|
|
212
debian/changelog
vendored
212
debian/changelog
vendored
@ -1,212 +0,0 @@
|
|||||||
git-core (1.0.0a-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 1.0.0a to include the following fixes:
|
|
||||||
|
|
||||||
- Avoid misleading success message on error (Johannes)
|
|
||||||
- objects/info/packs: work around bug in http-fetch.c::fetch_indices()
|
|
||||||
- http-fetch.c: fix objects/info/pack parsing.
|
|
||||||
- An off-by-one bug found by valgrind (Pavel)
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Wed, 21 Dec 2005 13:17:17 -0800
|
|
||||||
|
|
||||||
git-core (1.0.0-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 1.0.0
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Wed, 21 Dec 2005 00:01:00 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9n-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9n aka 1.0rc6
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Wed, 14 Dec 2005 17:27:08 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9m-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9m aka 1.0rc5
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sun, 11 Dec 2005 16:48:06 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9l-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9l aka 1.0rc4
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sat, 3 Dec 2005 23:45:23 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9k-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9k but not 1.0rc yet.
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Fri, 25 Nov 2005 16:33:11 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9j-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9j aka 1.0rc3
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Wed, 16 Nov 2005 20:39:55 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9i-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9i aka 1.0rc2
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Mon, 14 Nov 2005 18:38:27 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9h-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9h
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Fri, 11 Nov 2005 22:33:18 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9g-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9g
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Wed, 9 Nov 2005 21:01:55 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9f-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9f
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Tue, 8 Nov 2005 01:21:52 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9e-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9e
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sun, 6 Nov 2005 18:37:18 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9d-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9d
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sat, 5 Nov 2005 11:46:37 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9c-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9c
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Thu, 3 Nov 2005 15:44:54 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9b-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9b
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Tue, 1 Nov 2005 21:39:39 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9a-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9a
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sun, 30 Oct 2005 15:03:32 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9.GIT-2) unstable; urgency=low
|
|
||||||
|
|
||||||
* Build Dependency did not include libexpat-dev.
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sun, 13 Nov 2005 01:55:34 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9.GIT-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* Do not scatter txt and html documentation into feature
|
|
||||||
subpackages. Do place man pages into them.
|
|
||||||
* Capture more cvs stuff into git-cvs package.
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Tue, 8 Nov 2005 01:19:06 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9.GIT-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* Test Build.
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sat, 5 Nov 2005 11:18:13 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* Split the git-core binary package into core, doc, and foreign SCM
|
|
||||||
interoperability modules.
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sat, 5 Nov 2005 11:18:13 -0800
|
|
||||||
|
|
||||||
git-core (0.99.9-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.9
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sat, 29 Oct 2005 14:34:30 -0700
|
|
||||||
|
|
||||||
git-core (0.99.8-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.8
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sun, 2 Oct 2005 12:54:26 -0700
|
|
||||||
|
|
||||||
git-core (0.99.7-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.7
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sat, 10 Sep 2005 18:36:39 -0700
|
|
||||||
|
|
||||||
git-core (0.99.6-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.6
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Wed, 24 Aug 2005 23:09:35 -0700
|
|
||||||
|
|
||||||
git-core (0.99.5-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* Enable git-send-email on Debian. There is no reason to shy
|
|
||||||
away from it, since we have the necessary Perl modules available.
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Thu, 25 Aug 2005 14:16:59 -0700
|
|
||||||
|
|
||||||
git-core (0.99.5-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* GIT 0.99.5
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Wed, 10 Aug 2005 22:05:00 -0700
|
|
||||||
|
|
||||||
git-core (0.99.4-4) unstable; urgency=low
|
|
||||||
|
|
||||||
* Mark git-tk as architecture neutral.
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Fri, 12 Aug 2005 13:25:00 -0700
|
|
||||||
|
|
||||||
git-core (0.99.4-3) unstable; urgency=low
|
|
||||||
|
|
||||||
* Split off gitk.
|
|
||||||
* Do not depend on diff which is an essential package.
|
|
||||||
* Use dh_movefiles, not dh_install, to stage two subpackages.
|
|
||||||
|
|
||||||
-- Matthias Urlichs <smurf@debian.org> Thu, 11 Aug 2005 01:43:24 +0200
|
|
||||||
|
|
||||||
git-core (0.99.4-2) unstable; urgency=low
|
|
||||||
|
|
||||||
* Git 0.99.4 official release.
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Wed, 10 Aug 2005 15:00:00 -0700
|
|
||||||
|
|
||||||
git-core (0.99.4-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* Pass prefix down to the submake when building.
|
|
||||||
|
|
||||||
-- Junio C Hamano <junkio@cox.net> Sat, 6 Aug 2005 13:00:00 -0700
|
|
||||||
|
|
||||||
git-core (0.99-2) unstable; urgency=low
|
|
||||||
|
|
||||||
* Conflict with the GNU Interactive Tools package, which also installs
|
|
||||||
/usr/bin/git.
|
|
||||||
* Use the Mozilla SHA1 code and/or the PPC assembly in preference to
|
|
||||||
OpenSSL. This is only a partial fix for the license issues with OpenSSL.
|
|
||||||
* Minor tweaks to the Depends.
|
|
||||||
|
|
||||||
-- Ryan Anderson <ryan@michonline.com> Sat, 23 Jul 2005 14:15:00 -0400
|
|
||||||
|
|
||||||
git-core (0.99-1) unstable; urgency=low
|
|
||||||
|
|
||||||
* Update deb package support to build correctly.
|
|
||||||
|
|
||||||
-- Ryan Anderson <ryan@michonline.com> Thu, 21 Jul 2005 02:03:32 -0400
|
|
||||||
|
|
||||||
git-core (0.99-0) unstable; urgency=low
|
|
||||||
|
|
||||||
* Initial deb package support
|
|
||||||
|
|
||||||
-- Eric Biederman <ebiederm@xmission.com> Tue, 12 Jul 2005 10:57:51 -0600
|
|
1
debian/compat
vendored
1
debian/compat
vendored
@ -1 +0,0 @@
|
|||||||
4
|
|
63
debian/control
vendored
63
debian/control
vendored
@ -1,63 +0,0 @@
|
|||||||
Source: git-core
|
|
||||||
Section: devel
|
|
||||||
Priority: optional
|
|
||||||
Maintainer: Junio C Hamano <junkio@cox.net>
|
|
||||||
Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev|libcurl3-gnutls-dev|libcurl3-openssl-dev, asciidoc (>= 7), xmlto, debhelper (>= 4.0.0), bc, libexpat-dev
|
|
||||||
Standards-Version: 3.6.1
|
|
||||||
|
|
||||||
Package: git-core
|
|
||||||
Architecture: any
|
|
||||||
Depends: ${shlibs:Depends}, ${perl:Depends}, ${misc:Depends}, rcs
|
|
||||||
Recommends: rsync, curl, ssh, python (>= 2.4.0), less
|
|
||||||
Suggests: cogito, patch
|
|
||||||
Conflicts: git, cogito (<< 0.13)
|
|
||||||
Description: The git content addressable filesystem
|
|
||||||
GIT comes in two layers. The bottom layer is merely an extremely fast
|
|
||||||
and flexible filesystem-based database designed to store directory trees
|
|
||||||
with regard to their history. The top layer is a SCM-like tool which
|
|
||||||
enables human beings to work with the database in a manner to a degree
|
|
||||||
similar to other SCM tools.
|
|
||||||
|
|
||||||
Package: git-doc
|
|
||||||
Architecture: all
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, git-core
|
|
||||||
Description: The git content addressable filesystem, Documentation
|
|
||||||
This package contains documentation for GIT.
|
|
||||||
|
|
||||||
Package: git-tk
|
|
||||||
Architecture: all
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, git-core, tk8.4
|
|
||||||
Description: The git content addressable filesystem, GUI add-on
|
|
||||||
This package contains 'gitk', the git revision tree visualizer.
|
|
||||||
|
|
||||||
Package: git-svn
|
|
||||||
Architecture: all
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, git-core, libsvn-core-perl (>= 1.2.1)
|
|
||||||
Suggests: subversion
|
|
||||||
Description: The git content addressable filesystem, SVN interoperability
|
|
||||||
This package contains 'git-svnimport', to import development history from
|
|
||||||
SVN repositories.
|
|
||||||
|
|
||||||
Package: git-arch
|
|
||||||
Architecture: all
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, git-core
|
|
||||||
Suggests: tla, bazaar
|
|
||||||
Description: The git content addressable filesystem, GNUArch interoperability
|
|
||||||
This package contains 'git-archimport', to import development history from
|
|
||||||
GNUArch repositories.
|
|
||||||
|
|
||||||
Package: git-cvs
|
|
||||||
Architecture: all
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, git-core, cvsps (>= 2.1)
|
|
||||||
Suggests: cvs
|
|
||||||
Description: The git content addressable filesystem, CVS interoperability
|
|
||||||
This package contains 'git-cvsimport', to import development history from
|
|
||||||
CVS repositories.
|
|
||||||
|
|
||||||
Package: git-email
|
|
||||||
Architecture: all
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, git-core, libmail-sendmail-perl, libemail-valid-perl
|
|
||||||
Description: The git content addressable filesystem, e-mail add-on
|
|
||||||
This package contains 'git-send-email', to send a series of patch e-mails.
|
|
||||||
|
|
||||||
|
|
24
debian/copyright
vendored
24
debian/copyright
vendored
@ -1,24 +0,0 @@
|
|||||||
This package was downloaded from ftp.kernel.org:/pub/software/scm/git/.
|
|
||||||
|
|
||||||
Upstream Author: Linus Torvalds and many others
|
|
||||||
|
|
||||||
Copyright:
|
|
||||||
|
|
||||||
Copyright 2005, Linus Torvalds and others.
|
|
||||||
|
|
||||||
This package is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; version 2 dated June, 1991.
|
|
||||||
|
|
||||||
This package is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this package; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
02111-1307, USA.
|
|
||||||
|
|
||||||
On Debian GNU/Linux systems, the complete text of the GNU General
|
|
||||||
Public License can be found in `/usr/share/common-licenses/GPL'.
|
|
1
debian/docs
vendored
1
debian/docs
vendored
@ -1 +0,0 @@
|
|||||||
README
|
|
2
debian/git-arch.files
vendored
2
debian/git-arch.files
vendored
@ -1,2 +0,0 @@
|
|||||||
/usr/bin/git-arch*
|
|
||||||
/usr/share/man/*/git-arch*
|
|
13
debian/git-core.doc-base
vendored
13
debian/git-core.doc-base
vendored
@ -1,13 +0,0 @@
|
|||||||
Document: git-core
|
|
||||||
Title: git reference
|
|
||||||
Abstract: This manual describes git
|
|
||||||
Section: Devel
|
|
||||||
|
|
||||||
Format: HTML
|
|
||||||
Index: /usr/share/doc/git-core/git.html
|
|
||||||
Files: /usr/share/doc/git-core/*.html
|
|
||||||
/usr/share/doc/git-core/*/*.html
|
|
||||||
|
|
||||||
Format: text
|
|
||||||
Files: /usr/share/doc/git-core/*.txt
|
|
||||||
/usr/share/doc/git-core/*/*.txt
|
|
1
debian/git-core.files
vendored
1
debian/git-core.files
vendored
@ -1 +0,0 @@
|
|||||||
/usr
|
|
2
debian/git-cvs.files
vendored
2
debian/git-cvs.files
vendored
@ -1,2 +0,0 @@
|
|||||||
/usr/bin/git-cvs*
|
|
||||||
/usr/share/man/*/git-cvs*
|
|
4
debian/git-doc.files
vendored
4
debian/git-doc.files
vendored
@ -1,4 +0,0 @@
|
|||||||
/usr/share/doc/git-core/*.txt
|
|
||||||
/usr/share/doc/git-core/*.html
|
|
||||||
/usr/share/doc/git-core/*/*.html
|
|
||||||
/usr/share/doc/git-core/*/*.txt
|
|
2
debian/git-email.files
vendored
2
debian/git-email.files
vendored
@ -1,2 +0,0 @@
|
|||||||
/usr/bin/git-send-email
|
|
||||||
/usr/share/man/*/git-send-email.*
|
|
2
debian/git-svn.files
vendored
2
debian/git-svn.files
vendored
@ -1,2 +0,0 @@
|
|||||||
/usr/bin/git-svn*
|
|
||||||
/usr/share/man/*/git-svn*
|
|
2
debian/git-tk.files
vendored
2
debian/git-tk.files
vendored
@ -1,2 +0,0 @@
|
|||||||
/usr/bin/gitk
|
|
||||||
/usr/share/man/man1/gitk.*
|
|
109
debian/rules
vendored
109
debian/rules
vendored
@ -1,109 +0,0 @@
|
|||||||
#!/usr/bin/make -f
|
|
||||||
# -*- makefile -*-
|
|
||||||
|
|
||||||
# Uncomment this to turn on verbose mode.
|
|
||||||
#export DH_VERBOSE=1
|
|
||||||
|
|
||||||
CFLAGS = -g -Wall
|
|
||||||
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
|
|
||||||
CFLAGS += -O0
|
|
||||||
else
|
|
||||||
CFLAGS += -O2
|
|
||||||
endif
|
|
||||||
export CFLAGS
|
|
||||||
|
|
||||||
#
|
|
||||||
# On PowerPC we compile against the hand-crafted assembly, on all
|
|
||||||
# other architectures we compile against GPL'ed sha1 code lifted
|
|
||||||
# from Mozilla. OpenSSL is strangely licensed and best avoided
|
|
||||||
# in Debian.
|
|
||||||
#
|
|
||||||
HOST_ARCH=$(shell dpkg-architecture -qDEB_HOST_ARCH)
|
|
||||||
ifeq (${HOST_ARCH},powerpc)
|
|
||||||
export PPC_SHA1=YesPlease
|
|
||||||
else
|
|
||||||
export MOZILLA_SHA1=YesPlease
|
|
||||||
endif
|
|
||||||
|
|
||||||
# We do have the requisite perl modules in the mainline, and
|
|
||||||
# have no reason to shy away from this script.
|
|
||||||
export WITH_SEND_EMAIL=YesPlease
|
|
||||||
|
|
||||||
PREFIX := /usr
|
|
||||||
MANDIR := /usr/share/man/
|
|
||||||
|
|
||||||
SRC := ./
|
|
||||||
DOC := Documentation/
|
|
||||||
DESTDIR := $(CURDIR)/debian/tmp
|
|
||||||
DOC_DESTDIR := $(DESTDIR)/usr/share/doc/git-core/
|
|
||||||
MAN_DESTDIR := $(DESTDIR)/$(MANDIR)
|
|
||||||
|
|
||||||
build: debian/build-stamp
|
|
||||||
debian/build-stamp:
|
|
||||||
dh_testdir
|
|
||||||
$(MAKE) prefix=$(PREFIX) PYTHON_PATH=/usr/bin/python2.4 all test doc
|
|
||||||
touch debian/build-stamp
|
|
||||||
|
|
||||||
debian-clean:
|
|
||||||
dh_testdir
|
|
||||||
dh_testroot
|
|
||||||
rm -f debian/build-stamp
|
|
||||||
dh_clean
|
|
||||||
|
|
||||||
clean: debian-clean
|
|
||||||
$(MAKE) clean
|
|
||||||
|
|
||||||
install: build
|
|
||||||
dh_testdir
|
|
||||||
dh_testroot
|
|
||||||
dh_clean -k
|
|
||||||
dh_installdirs
|
|
||||||
|
|
||||||
make DESTDIR=$(DESTDIR) prefix=$(PREFIX) mandir=$(MANDIR) \
|
|
||||||
install install-doc
|
|
||||||
|
|
||||||
make -C Documentation DESTDIR=$(DESTDIR) prefix=$(PREFIX) \
|
|
||||||
WEBDOC_DEST=$(DOC_DESTDIR) install-webdoc
|
|
||||||
|
|
||||||
dh_movefiles -p git-arch
|
|
||||||
dh_movefiles -p git-cvs
|
|
||||||
dh_movefiles -p git-svn
|
|
||||||
dh_movefiles -p git-tk
|
|
||||||
dh_movefiles -p git-email
|
|
||||||
dh_movefiles -p git-doc
|
|
||||||
dh_movefiles -p git-core
|
|
||||||
find debian/tmp -type d -o -print | sed -e 's/^/? /'
|
|
||||||
|
|
||||||
binary-arch: build install
|
|
||||||
dh_testdir
|
|
||||||
dh_testroot
|
|
||||||
dh_installchangelogs -a
|
|
||||||
dh_installdocs -a
|
|
||||||
dh_strip -a
|
|
||||||
dh_compress -a
|
|
||||||
dh_fixperms -a
|
|
||||||
dh_perl -a
|
|
||||||
dh_makeshlibs -a
|
|
||||||
dh_installdeb -a
|
|
||||||
dh_shlibdeps -a
|
|
||||||
dh_gencontrol -a
|
|
||||||
dh_md5sums -a
|
|
||||||
dh_builddeb -a
|
|
||||||
|
|
||||||
binary-indep: build install
|
|
||||||
dh_testdir
|
|
||||||
dh_testroot
|
|
||||||
dh_installchangelogs -i
|
|
||||||
dh_installdocs -i
|
|
||||||
dh_compress -i
|
|
||||||
dh_fixperms -i
|
|
||||||
dh_makeshlibs -i
|
|
||||||
dh_installdeb -i
|
|
||||||
dh_shlibdeps -i
|
|
||||||
dh_gencontrol -i
|
|
||||||
dh_md5sums -i
|
|
||||||
dh_builddeb -i
|
|
||||||
|
|
||||||
binary: binary-arch binary-indep
|
|
||||||
|
|
||||||
.PHONY: build clean binary install clean debian-clean
|
|
10
delta.h
10
delta.h
@ -19,14 +19,14 @@ extern void *patch_delta(void *src_buf, unsigned long src_size,
|
|||||||
static inline unsigned long get_delta_hdr_size(const unsigned char **datap)
|
static inline unsigned long get_delta_hdr_size(const unsigned char **datap)
|
||||||
{
|
{
|
||||||
const unsigned char *data = *datap;
|
const unsigned char *data = *datap;
|
||||||
unsigned char cmd = *data++;
|
unsigned char cmd;
|
||||||
unsigned long size = cmd & ~0x80;
|
unsigned long size = 0;
|
||||||
int i = 7;
|
int i = 0;
|
||||||
while (cmd & 0x80) {
|
do {
|
||||||
cmd = *data++;
|
cmd = *data++;
|
||||||
size |= (cmd & ~0x80) << i;
|
size |= (cmd & ~0x80) << i;
|
||||||
i += 7;
|
i += 7;
|
||||||
}
|
} while (cmd & 0x80);
|
||||||
*datap = data;
|
*datap = data;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
173
describe.c
Normal file
173
describe.c
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#include "cache.h"
|
||||||
|
#include "commit.h"
|
||||||
|
#include "tag.h"
|
||||||
|
#include "refs.h"
|
||||||
|
|
||||||
|
#define SEEN (1u << 0)
|
||||||
|
|
||||||
|
static const char describe_usage[] =
|
||||||
|
"git-describe [--all] [--tags] [--abbrev=<n>] <committish>*";
|
||||||
|
|
||||||
|
static int all = 0; /* Default to annotated tags only */
|
||||||
|
static int tags = 0; /* But allow any tags if --tags is specified */
|
||||||
|
|
||||||
|
static int abbrev = DEFAULT_ABBREV;
|
||||||
|
|
||||||
|
static int names = 0, allocs = 0;
|
||||||
|
static struct commit_name {
|
||||||
|
const struct commit *commit;
|
||||||
|
int prio; /* annotated tag = 2, tag = 1, head = 0 */
|
||||||
|
char path[FLEX_ARRAY]; /* more */
|
||||||
|
} **name_array = NULL;
|
||||||
|
|
||||||
|
static struct commit_name *match(struct commit *cmit)
|
||||||
|
{
|
||||||
|
int i = names;
|
||||||
|
struct commit_name **p = name_array;
|
||||||
|
|
||||||
|
while (i-- > 0) {
|
||||||
|
struct commit_name *n = *p++;
|
||||||
|
if (n->commit == cmit)
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_to_known_names(const char *path,
|
||||||
|
const struct commit *commit,
|
||||||
|
int prio)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
int len = strlen(path)+1;
|
||||||
|
struct commit_name *name = xmalloc(sizeof(struct commit_name) + len);
|
||||||
|
|
||||||
|
name->commit = commit;
|
||||||
|
name->prio = prio;
|
||||||
|
memcpy(name->path, path, len);
|
||||||
|
idx = names;
|
||||||
|
if (idx >= allocs) {
|
||||||
|
allocs = (idx + 50) * 3 / 2;
|
||||||
|
name_array = xrealloc(name_array, allocs*sizeof(*name_array));
|
||||||
|
}
|
||||||
|
name_array[idx] = name;
|
||||||
|
names = ++idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_name(const char *path, const unsigned char *sha1)
|
||||||
|
{
|
||||||
|
struct commit *commit = lookup_commit_reference_gently(sha1, 1);
|
||||||
|
struct object *object;
|
||||||
|
int prio;
|
||||||
|
|
||||||
|
if (!commit)
|
||||||
|
return 0;
|
||||||
|
object = parse_object(sha1);
|
||||||
|
/* If --all, then any refs are used.
|
||||||
|
* If --tags, then any tags are used.
|
||||||
|
* Otherwise only annotated tags are used.
|
||||||
|
*/
|
||||||
|
if (!strncmp(path, "refs/tags/", 10)) {
|
||||||
|
if (object->type == tag_type)
|
||||||
|
prio = 2;
|
||||||
|
else
|
||||||
|
prio = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prio = 0;
|
||||||
|
|
||||||
|
if (!all) {
|
||||||
|
if (!prio)
|
||||||
|
return 0;
|
||||||
|
if (!tags && prio < 2)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
add_to_known_names(all ? path + 5 : path + 10, commit, prio);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare_names(const void *_a, const void *_b)
|
||||||
|
{
|
||||||
|
struct commit_name *a = *(struct commit_name **)_a;
|
||||||
|
struct commit_name *b = *(struct commit_name **)_b;
|
||||||
|
unsigned long a_date = a->commit->date;
|
||||||
|
unsigned long b_date = b->commit->date;
|
||||||
|
|
||||||
|
if (a->prio != b->prio)
|
||||||
|
return b->prio - a->prio;
|
||||||
|
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void describe(char *arg, int last_one)
|
||||||
|
{
|
||||||
|
unsigned char sha1[20];
|
||||||
|
struct commit *cmit;
|
||||||
|
struct commit_list *list;
|
||||||
|
static int initialized = 0;
|
||||||
|
struct commit_name *n;
|
||||||
|
|
||||||
|
if (get_sha1(arg, sha1) < 0)
|
||||||
|
usage(describe_usage);
|
||||||
|
cmit = lookup_commit_reference(sha1);
|
||||||
|
if (!cmit)
|
||||||
|
usage(describe_usage);
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = 1;
|
||||||
|
for_each_ref(get_name);
|
||||||
|
qsort(name_array, names, sizeof(*name_array), compare_names);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = match(cmit);
|
||||||
|
if (n) {
|
||||||
|
printf("%s\n", n->path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = NULL;
|
||||||
|
commit_list_insert(cmit, &list);
|
||||||
|
while (list) {
|
||||||
|
struct commit *c = pop_most_recent_commit(&list, SEEN);
|
||||||
|
n = match(c);
|
||||||
|
if (n) {
|
||||||
|
printf("%s-g%s\n", n->path,
|
||||||
|
find_unique_abbrev(cmit->object.sha1, abbrev));
|
||||||
|
if (!last_one)
|
||||||
|
clear_commit_marks(cmit, SEEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
die("cannot describe '%s'", sha1_to_hex(cmit->object.sha1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
const char *arg = argv[i];
|
||||||
|
|
||||||
|
if (*arg != '-')
|
||||||
|
break;
|
||||||
|
else if (!strcmp(arg, "--all"))
|
||||||
|
all = 1;
|
||||||
|
else if (!strcmp(arg, "--tags"))
|
||||||
|
tags = 1;
|
||||||
|
else if (!strncmp(arg, "--abbrev=", 9)) {
|
||||||
|
abbrev = strtoul(arg + 9, NULL, 10);
|
||||||
|
if (abbrev < MINIMUM_ABBREV || 40 <= abbrev)
|
||||||
|
abbrev = DEFAULT_ABBREV;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
usage(describe_usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == argc)
|
||||||
|
describe("HEAD", 1);
|
||||||
|
else
|
||||||
|
while (i < argc) {
|
||||||
|
describe(argv[i], (i == argc - 1));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
39
diff-delta.c
39
diff-delta.c
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "delta.h"
|
#include "delta.h"
|
||||||
|
#include "zlib.h"
|
||||||
|
|
||||||
|
|
||||||
/* block size: min = 16, max = 64k, power of 2 */
|
/* block size: min = 16, max = 64k, power of 2 */
|
||||||
@ -30,44 +31,6 @@
|
|||||||
#define GR_PRIME 0x9e370001
|
#define GR_PRIME 0x9e370001
|
||||||
#define HASH(v, b) (((unsigned int)(v) * GR_PRIME) >> (32 - (b)))
|
#define HASH(v, b) (((unsigned int)(v) * GR_PRIME) >> (32 - (b)))
|
||||||
|
|
||||||
/* largest prime smaller than 65536 */
|
|
||||||
#define BASE 65521
|
|
||||||
|
|
||||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
|
||||||
#define NMAX 5552
|
|
||||||
|
|
||||||
#define DO1(buf, i) { s1 += buf[i]; s2 += s1; }
|
|
||||||
#define DO2(buf, i) DO1(buf, i); DO1(buf, i + 1);
|
|
||||||
#define DO4(buf, i) DO2(buf, i); DO2(buf, i + 2);
|
|
||||||
#define DO8(buf, i) DO4(buf, i); DO4(buf, i + 4);
|
|
||||||
#define DO16(buf) DO8(buf, 0); DO8(buf, 8);
|
|
||||||
|
|
||||||
static unsigned int adler32(unsigned int adler, const unsigned char *buf, int len)
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
unsigned int s1 = adler & 0xffff;
|
|
||||||
unsigned int s2 = adler >> 16;
|
|
||||||
|
|
||||||
while (len > 0) {
|
|
||||||
k = MIN(len, NMAX);
|
|
||||||
len -= k;
|
|
||||||
while (k >= 16) {
|
|
||||||
DO16(buf);
|
|
||||||
buf += 16;
|
|
||||||
k -= 16;
|
|
||||||
}
|
|
||||||
if (k != 0)
|
|
||||||
do {
|
|
||||||
s1 += *buf++;
|
|
||||||
s2 += s1;
|
|
||||||
} while (--k);
|
|
||||||
s1 %= BASE;
|
|
||||||
s2 %= BASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (s2 << 16) | s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int hashbits(unsigned int size)
|
static unsigned int hashbits(unsigned int size)
|
||||||
{
|
{
|
||||||
unsigned int val = 1, bits = 0;
|
unsigned int val = 1, bits = 0;
|
||||||
|
56
diff-files.c
56
diff-files.c
@ -7,12 +7,14 @@
|
|||||||
#include "diff.h"
|
#include "diff.h"
|
||||||
|
|
||||||
static const char diff_files_usage[] =
|
static const char diff_files_usage[] =
|
||||||
"git-diff-files [-q] [-0/-1/2/3] [<common diff options>] [<path>...]"
|
"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
|
||||||
COMMON_DIFF_OPTIONS_HELP;
|
COMMON_DIFF_OPTIONS_HELP;
|
||||||
|
|
||||||
static struct diff_options diff_options;
|
static struct diff_options diff_options;
|
||||||
static int silent = 0;
|
static int silent = 0;
|
||||||
static int diff_unmerged_stage = 2;
|
static int diff_unmerged_stage = 2;
|
||||||
|
static int combine_merges = 0;
|
||||||
|
static int dense_combined_merges = 0;
|
||||||
|
|
||||||
static void show_unmerge(const char *path)
|
static void show_unmerge(const char *path)
|
||||||
{
|
{
|
||||||
@ -66,6 +68,10 @@ int main(int argc, const char **argv)
|
|||||||
; /* no-op */
|
; /* no-op */
|
||||||
else if (!strcmp(argv[1], "-s"))
|
else if (!strcmp(argv[1], "-s"))
|
||||||
; /* no-op */
|
; /* no-op */
|
||||||
|
else if (!strcmp(argv[1], "-c"))
|
||||||
|
combine_merges = 1;
|
||||||
|
else if (!strcmp(argv[1], "--cc"))
|
||||||
|
dense_combined_merges = combine_merges = 1;
|
||||||
else {
|
else {
|
||||||
int diff_opt_cnt;
|
int diff_opt_cnt;
|
||||||
diff_opt_cnt = diff_opt_parse(&diff_options,
|
diff_opt_cnt = diff_opt_parse(&diff_options,
|
||||||
@ -82,6 +88,8 @@ int main(int argc, const char **argv)
|
|||||||
}
|
}
|
||||||
argv++; argc--;
|
argv++; argc--;
|
||||||
}
|
}
|
||||||
|
if (dense_combined_merges)
|
||||||
|
diff_options.output_format = DIFF_FORMAT_PATCH;
|
||||||
|
|
||||||
/* Find the directory, and set up the pathspec */
|
/* Find the directory, and set up the pathspec */
|
||||||
pathspec = get_pathspec(prefix, argv + 1);
|
pathspec = get_pathspec(prefix, argv + 1);
|
||||||
@ -108,14 +116,44 @@ int main(int argc, const char **argv)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ce_stage(ce)) {
|
if (ce_stage(ce)) {
|
||||||
show_unmerge(ce->name);
|
struct {
|
||||||
|
struct combine_diff_path p;
|
||||||
|
struct combine_diff_parent filler[5];
|
||||||
|
} combine;
|
||||||
|
int num_compare_stages = 0;
|
||||||
|
|
||||||
|
combine.p.next = NULL;
|
||||||
|
combine.p.len = ce_namelen(ce);
|
||||||
|
combine.p.path = xmalloc(combine.p.len + 1);
|
||||||
|
memcpy(combine.p.path, ce->name, combine.p.len);
|
||||||
|
combine.p.path[combine.p.len] = 0;
|
||||||
|
combine.p.mode = 0;
|
||||||
|
memset(combine.p.sha1, 0, 20);
|
||||||
|
memset(&combine.p.parent[0], 0,
|
||||||
|
sizeof(combine.filler));
|
||||||
|
|
||||||
while (i < entries) {
|
while (i < entries) {
|
||||||
struct cache_entry *nce = active_cache[i];
|
struct cache_entry *nce = active_cache[i];
|
||||||
|
int stage;
|
||||||
|
|
||||||
if (strcmp(ce->name, nce->name))
|
if (strcmp(ce->name, nce->name))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Stage #2 (ours) is the first parent,
|
||||||
|
* stage #3 (theirs) is the second.
|
||||||
|
*/
|
||||||
|
stage = ce_stage(nce);
|
||||||
|
if (2 <= stage) {
|
||||||
|
int mode = ntohl(nce->ce_mode);
|
||||||
|
num_compare_stages++;
|
||||||
|
memcpy(combine.p.parent[stage-2].sha1,
|
||||||
|
nce->sha1, 20);
|
||||||
|
combine.p.parent[stage-2].mode =
|
||||||
|
DIFF_FILE_CANON_MODE(mode);
|
||||||
|
}
|
||||||
|
|
||||||
/* diff against the proper unmerged stage */
|
/* diff against the proper unmerged stage */
|
||||||
if (ce_stage(nce) == diff_unmerged_stage)
|
if (stage == diff_unmerged_stage)
|
||||||
ce = nce;
|
ce = nce;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -123,10 +161,22 @@ int main(int argc, const char **argv)
|
|||||||
* Compensate for loop update
|
* Compensate for loop update
|
||||||
*/
|
*/
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
|
if (combine_merges && num_compare_stages == 2) {
|
||||||
|
show_combined_diff(&combine.p, 2,
|
||||||
|
dense_combined_merges,
|
||||||
|
NULL,
|
||||||
|
&diff_options);
|
||||||
|
free(combine.p.path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
free(combine.p.path);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Show the diff for the 'ce' if we found the one
|
* Show the diff for the 'ce' if we found the one
|
||||||
* from the desired stage.
|
* from the desired stage.
|
||||||
*/
|
*/
|
||||||
|
show_unmerge(ce->name);
|
||||||
if (ce_stage(ce) != diff_unmerged_stage)
|
if (ce_stage(ce) != diff_unmerged_stage)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
18
diff-index.c
18
diff-index.c
@ -1,4 +1,5 @@
|
|||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include "tree.h"
|
||||||
#include "diff.h"
|
#include "diff.h"
|
||||||
|
|
||||||
static int cached_only = 0;
|
static int cached_only = 0;
|
||||||
@ -116,7 +117,7 @@ static int diff_cache(struct cache_entry **ac, int entries, const char **pathspe
|
|||||||
/* We come here with ce pointing at stage 1
|
/* We come here with ce pointing at stage 1
|
||||||
* (original tree) and ac[1] pointing at stage
|
* (original tree) and ac[1] pointing at stage
|
||||||
* 3 (unmerged). show-modified with
|
* 3 (unmerged). show-modified with
|
||||||
* report-mising set to false does not say the
|
* report-missing set to false does not say the
|
||||||
* file is deleted but reports true if work
|
* file is deleted but reports true if work
|
||||||
* tree does not have it, in which case we
|
* tree does not have it, in which case we
|
||||||
* fall through to report the unmerged state.
|
* fall through to report the unmerged state.
|
||||||
@ -174,8 +175,7 @@ int main(int argc, const char **argv)
|
|||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
const char *prefix = setup_git_directory();
|
const char *prefix = setup_git_directory();
|
||||||
const char **pathspec = NULL;
|
const char **pathspec = NULL;
|
||||||
void *tree;
|
struct tree *tree;
|
||||||
unsigned long size;
|
|
||||||
int ret;
|
int ret;
|
||||||
int allow_options = 1;
|
int allow_options = 1;
|
||||||
int i;
|
int i;
|
||||||
@ -201,6 +201,14 @@ int main(int argc, const char **argv)
|
|||||||
/* We accept the -r flag just to look like git-diff-tree */
|
/* We accept the -r flag just to look like git-diff-tree */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(arg, "--cc"))
|
||||||
|
/*
|
||||||
|
* I _think_ "diff-index --cached HEAD" with an
|
||||||
|
* unmerged index could show something else
|
||||||
|
* later, but pretend --cc is the same as -p for
|
||||||
|
* now. "git diff" uses --cc by default.
|
||||||
|
*/
|
||||||
|
argv[i] = arg = "-p";
|
||||||
diff_opt_cnt = diff_opt_parse(&diff_options, argv + i,
|
diff_opt_cnt = diff_opt_parse(&diff_options, argv + i,
|
||||||
argc - i);
|
argc - i);
|
||||||
if (diff_opt_cnt < 0)
|
if (diff_opt_cnt < 0)
|
||||||
@ -233,10 +241,10 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
mark_merge_entries();
|
mark_merge_entries();
|
||||||
|
|
||||||
tree = read_object_with_reference(sha1, "tree", &size, NULL);
|
tree = parse_tree_indirect(sha1);
|
||||||
if (!tree)
|
if (!tree)
|
||||||
die("bad tree object %s", tree_name);
|
die("bad tree object %s", tree_name);
|
||||||
if (read_tree(tree, size, 1, pathspec))
|
if (read_tree(tree, 1, pathspec))
|
||||||
die("unable to read tree object %s", tree_name);
|
die("unable to read tree object %s", tree_name);
|
||||||
|
|
||||||
ret = diff_cache(active_cache, active_nr, pathspec);
|
ret = diff_cache(active_cache, active_nr, pathspec);
|
||||||
|
128
diff-tree.c
128
diff-tree.c
@ -6,7 +6,10 @@ static int show_root_diff = 0;
|
|||||||
static int no_commit_id = 0;
|
static int no_commit_id = 0;
|
||||||
static int verbose_header = 0;
|
static int verbose_header = 0;
|
||||||
static int ignore_merges = 1;
|
static int ignore_merges = 1;
|
||||||
|
static int combine_merges = 0;
|
||||||
|
static int dense_combined_merges = 0;
|
||||||
static int read_stdin = 0;
|
static int read_stdin = 0;
|
||||||
|
static int always_show_header = 0;
|
||||||
|
|
||||||
static const char *header = NULL;
|
static const char *header = NULL;
|
||||||
static const char *header_prefix = "";
|
static const char *header_prefix = "";
|
||||||
@ -64,12 +67,13 @@ static int diff_root_tree(const unsigned char *new, const char *base)
|
|||||||
|
|
||||||
static const char *generate_header(const unsigned char *commit_sha1,
|
static const char *generate_header(const unsigned char *commit_sha1,
|
||||||
const unsigned char *parent_sha1,
|
const unsigned char *parent_sha1,
|
||||||
const char *msg)
|
const struct commit *commit)
|
||||||
{
|
{
|
||||||
static char this_header[16384];
|
static char this_header[16384];
|
||||||
int offset;
|
int offset;
|
||||||
unsigned long len;
|
unsigned long len;
|
||||||
int abbrev = diff_options.abbrev;
|
int abbrev = diff_options.abbrev;
|
||||||
|
const char *msg = commit->buffer;
|
||||||
|
|
||||||
if (!verbose_header)
|
if (!verbose_header)
|
||||||
return sha1_to_hex(commit_sha1);
|
return sha1_to_hex(commit_sha1);
|
||||||
@ -79,44 +83,53 @@ static const char *generate_header(const unsigned char *commit_sha1,
|
|||||||
offset = sprintf(this_header, "%s%s ",
|
offset = sprintf(this_header, "%s%s ",
|
||||||
header_prefix,
|
header_prefix,
|
||||||
diff_unique_abbrev(commit_sha1, abbrev));
|
diff_unique_abbrev(commit_sha1, abbrev));
|
||||||
|
if (commit_sha1 != parent_sha1)
|
||||||
offset += sprintf(this_header + offset, "(from %s)\n",
|
offset += sprintf(this_header + offset, "(from %s)\n",
|
||||||
parent_sha1 ?
|
parent_sha1
|
||||||
diff_unique_abbrev(parent_sha1, abbrev) : "root");
|
? diff_unique_abbrev(parent_sha1, abbrev)
|
||||||
offset += pretty_print_commit(commit_format, msg, len,
|
: "root");
|
||||||
|
else
|
||||||
|
offset += sprintf(this_header + offset, "(from parents)\n");
|
||||||
|
offset += pretty_print_commit(commit_format, commit, len,
|
||||||
this_header + offset,
|
this_header + offset,
|
||||||
sizeof(this_header) - offset);
|
sizeof(this_header) - offset, abbrev);
|
||||||
|
if (always_show_header) {
|
||||||
|
puts(this_header);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return this_header;
|
return this_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int diff_tree_commit(const unsigned char *commit_sha1)
|
static int diff_tree_commit(struct commit *commit)
|
||||||
{
|
{
|
||||||
struct commit *commit;
|
|
||||||
struct commit_list *parents;
|
struct commit_list *parents;
|
||||||
char name[50];
|
unsigned const char *sha1 = commit->object.sha1;
|
||||||
unsigned char sha1[20];
|
|
||||||
|
|
||||||
sprintf(name, "%s^0", sha1_to_hex(commit_sha1));
|
|
||||||
if (get_sha1(name, sha1))
|
|
||||||
return -1;
|
|
||||||
name[40] = 0;
|
|
||||||
commit = lookup_commit(sha1);
|
|
||||||
|
|
||||||
/* Root commit? */
|
/* Root commit? */
|
||||||
if (show_root_diff && !commit->parents) {
|
if (show_root_diff && !commit->parents) {
|
||||||
header = generate_header(sha1, NULL, commit->buffer);
|
header = generate_header(sha1, NULL, commit);
|
||||||
diff_root_tree(commit_sha1, "");
|
diff_root_tree(sha1, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* More than one parent? */
|
/* More than one parent? */
|
||||||
if (ignore_merges && commit->parents && commit->parents->next)
|
if (commit->parents && commit->parents->next) {
|
||||||
|
if (ignore_merges)
|
||||||
return 0;
|
return 0;
|
||||||
|
else if (combine_merges) {
|
||||||
|
header = generate_header(sha1, sha1, commit);
|
||||||
|
header = diff_tree_combined_merge(sha1, header,
|
||||||
|
dense_combined_merges,
|
||||||
|
&diff_options);
|
||||||
|
if (!header && verbose_header)
|
||||||
|
header_prefix = "\ndiff-tree ";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (parents = commit->parents; parents; parents = parents->next) {
|
for (parents = commit->parents; parents; parents = parents->next) {
|
||||||
struct commit *parent = parents->item;
|
struct commit *parent = parents->item;
|
||||||
header = generate_header(sha1,
|
header = generate_header(sha1, parent->object.sha1, commit);
|
||||||
parent->object.sha1,
|
diff_tree_sha1_top(parent->object.sha1, sha1, "");
|
||||||
commit->buffer);
|
|
||||||
diff_tree_sha1_top(parent->object.sha1, commit_sha1, "");
|
|
||||||
if (!header && verbose_header) {
|
if (!header && verbose_header) {
|
||||||
header_prefix = "\ndiff-tree ";
|
header_prefix = "\ndiff-tree ";
|
||||||
/*
|
/*
|
||||||
@ -128,33 +141,54 @@ static int diff_tree_commit(const unsigned char *commit_sha1)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int diff_tree_commit_sha1(const unsigned char *sha1)
|
||||||
|
{
|
||||||
|
struct commit *commit = lookup_commit_reference(sha1);
|
||||||
|
if (!commit)
|
||||||
|
return -1;
|
||||||
|
return diff_tree_commit(commit);
|
||||||
|
}
|
||||||
|
|
||||||
static int diff_tree_stdin(char *line)
|
static int diff_tree_stdin(char *line)
|
||||||
{
|
{
|
||||||
int len = strlen(line);
|
int len = strlen(line);
|
||||||
unsigned char commit[20], parent[20];
|
unsigned char sha1[20];
|
||||||
static char this_header[1000];
|
struct commit *commit;
|
||||||
int abbrev = diff_options.abbrev;
|
|
||||||
|
|
||||||
if (!len || line[len-1] != '\n')
|
if (!len || line[len-1] != '\n')
|
||||||
return -1;
|
return -1;
|
||||||
line[len-1] = 0;
|
line[len-1] = 0;
|
||||||
if (get_sha1_hex(line, commit))
|
if (get_sha1_hex(line, sha1))
|
||||||
return -1;
|
return -1;
|
||||||
if (isspace(line[40]) && !get_sha1_hex(line+41, parent)) {
|
commit = lookup_commit(sha1);
|
||||||
line[40] = 0;
|
if (!commit || parse_commit(commit))
|
||||||
line[81] = 0;
|
return -1;
|
||||||
sprintf(this_header, "%s (from %s)\n",
|
if (isspace(line[40]) && !get_sha1_hex(line+41, sha1)) {
|
||||||
diff_unique_abbrev(commit, abbrev),
|
/* Graft the fake parents locally to the commit */
|
||||||
diff_unique_abbrev(parent, abbrev));
|
int pos = 41;
|
||||||
header = this_header;
|
struct commit_list **pptr, *parents;
|
||||||
return diff_tree_sha1_top(parent, commit, "");
|
|
||||||
|
/* Free the real parent list */
|
||||||
|
for (parents = commit->parents; parents; ) {
|
||||||
|
struct commit_list *tmp = parents->next;
|
||||||
|
free(parents);
|
||||||
|
parents = tmp;
|
||||||
|
}
|
||||||
|
commit->parents = NULL;
|
||||||
|
pptr = &(commit->parents);
|
||||||
|
while (line[pos] && !get_sha1_hex(line + pos, sha1)) {
|
||||||
|
struct commit *parent = lookup_commit(sha1);
|
||||||
|
if (parent) {
|
||||||
|
pptr = &commit_list_insert(parent, pptr)->next;
|
||||||
|
}
|
||||||
|
pos += 41;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
line[40] = 0;
|
|
||||||
return diff_tree_commit(commit);
|
return diff_tree_commit(commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char diff_tree_usage[] =
|
static const char diff_tree_usage[] =
|
||||||
"git-diff-tree [--stdin] [-m] [-s] [-v] [--pretty] [-t] [-r] [--root] "
|
"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
|
||||||
"[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
|
"[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
|
||||||
" -r diff recursively\n"
|
" -r diff recursively\n"
|
||||||
" --root include the initial commit as diff against /dev/null\n"
|
" --root include the initial commit as diff against /dev/null\n"
|
||||||
@ -217,6 +251,14 @@ int main(int argc, const char **argv)
|
|||||||
ignore_merges = 0;
|
ignore_merges = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(arg, "-c")) {
|
||||||
|
combine_merges = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(arg, "--cc")) {
|
||||||
|
dense_combined_merges = combine_merges = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "-v")) {
|
if (!strcmp(arg, "-v")) {
|
||||||
verbose_header = 1;
|
verbose_header = 1;
|
||||||
header_prefix = "diff-tree ";
|
header_prefix = "diff-tree ";
|
||||||
@ -240,8 +282,20 @@ int main(int argc, const char **argv)
|
|||||||
no_commit_id = 1;
|
no_commit_id = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(arg, "--always")) {
|
||||||
|
always_show_header = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
usage(diff_tree_usage);
|
usage(diff_tree_usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (combine_merges)
|
||||||
|
ignore_merges = 0;
|
||||||
|
|
||||||
|
/* We can only do dense combined merges with diff output */
|
||||||
|
if (dense_combined_merges)
|
||||||
|
diff_options.output_format = DIFF_FORMAT_PATCH;
|
||||||
|
|
||||||
if (diff_options.output_format == DIFF_FORMAT_PATCH)
|
if (diff_options.output_format == DIFF_FORMAT_PATCH)
|
||||||
diff_options.recursive = 1;
|
diff_options.recursive = 1;
|
||||||
|
|
||||||
@ -254,7 +308,7 @@ int main(int argc, const char **argv)
|
|||||||
usage(diff_tree_usage);
|
usage(diff_tree_usage);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
diff_tree_commit(sha1[0]);
|
diff_tree_commit_sha1(sha1[0]);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
diff_tree_sha1_top(sha1[0], sha1[1], "");
|
diff_tree_sha1_top(sha1[0], sha1[1], "");
|
||||||
|
35
diff.c
35
diff.c
@ -504,9 +504,9 @@ static void prepare_temp_file(const char *name,
|
|||||||
}
|
}
|
||||||
if (S_ISLNK(st.st_mode)) {
|
if (S_ISLNK(st.st_mode)) {
|
||||||
int ret;
|
int ret;
|
||||||
char *buf, buf_[1024];
|
char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
|
||||||
buf = ((sizeof(buf_) < st.st_size) ?
|
if (sizeof(buf) <= st.st_size)
|
||||||
xmalloc(st.st_size) : buf_);
|
die("symlink too long: %s", name);
|
||||||
ret = readlink(name, buf, st.st_size);
|
ret = readlink(name, buf, st.st_size);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
die("readlink(%s)", name);
|
die("readlink(%s)", name);
|
||||||
@ -555,6 +555,8 @@ static void remove_tempfile(void)
|
|||||||
static void remove_tempfile_on_signal(int signo)
|
static void remove_tempfile_on_signal(int signo)
|
||||||
{
|
{
|
||||||
remove_tempfile();
|
remove_tempfile();
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
raise(signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* An external diff command takes:
|
/* An external diff command takes:
|
||||||
@ -650,7 +652,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
|
|||||||
if (DIFF_FILE_VALID(one)) {
|
if (DIFF_FILE_VALID(one)) {
|
||||||
if (!one->sha1_valid) {
|
if (!one->sha1_valid) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(one->path, &st) < 0)
|
if (lstat(one->path, &st) < 0)
|
||||||
die("stat %s", one->path);
|
die("stat %s", one->path);
|
||||||
if (index_path(one->sha1, one->path, &st, 0))
|
if (index_path(one->sha1, one->path, &st, 0))
|
||||||
die("cannot hash %s\n", one->path);
|
die("cannot hash %s\n", one->path);
|
||||||
@ -723,7 +725,7 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
|||||||
|
|
||||||
if (memcmp(one->sha1, two->sha1, 20)) {
|
if (memcmp(one->sha1, two->sha1, 20)) {
|
||||||
char one_sha1[41];
|
char one_sha1[41];
|
||||||
int abbrev = o->full_index ? 40 : DIFF_DEFAULT_INDEX_ABBREV;
|
int abbrev = o->full_index ? 40 : DEFAULT_ABBREV;
|
||||||
memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
|
memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
|
||||||
|
|
||||||
len += snprintf(msg + len, sizeof(msg) - len,
|
len += snprintf(msg + len, sizeof(msg) - len,
|
||||||
@ -787,7 +789,7 @@ int diff_setup_done(struct diff_options *options)
|
|||||||
* so it is safe for us to do this here. Also
|
* so it is safe for us to do this here. Also
|
||||||
* it does not smudge active_cache or active_nr
|
* it does not smudge active_cache or active_nr
|
||||||
* when it fails, so we do not have to worry about
|
* when it fails, so we do not have to worry about
|
||||||
* cleaning it up oufselves either.
|
* cleaning it up ourselves either.
|
||||||
*/
|
*/
|
||||||
read_cache();
|
read_cache();
|
||||||
}
|
}
|
||||||
@ -846,9 +848,14 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
|||||||
else if (!strcmp(arg, "--find-copies-harder"))
|
else if (!strcmp(arg, "--find-copies-harder"))
|
||||||
options->find_copies_harder = 1;
|
options->find_copies_harder = 1;
|
||||||
else if (!strcmp(arg, "--abbrev"))
|
else if (!strcmp(arg, "--abbrev"))
|
||||||
options->abbrev = DIFF_DEFAULT_ABBREV;
|
options->abbrev = DEFAULT_ABBREV;
|
||||||
else if (!strncmp(arg, "--abbrev=", 9))
|
else if (!strncmp(arg, "--abbrev=", 9)) {
|
||||||
options->abbrev = strtoul(arg + 9, NULL, 10);
|
options->abbrev = strtoul(arg + 9, NULL, 10);
|
||||||
|
if (options->abbrev < MINIMUM_ABBREV)
|
||||||
|
options->abbrev = MINIMUM_ABBREV;
|
||||||
|
else if (40 < options->abbrev)
|
||||||
|
options->abbrev = 40;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
@ -956,7 +963,7 @@ void diff_free_filepair(struct diff_filepair *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* This is different from find_unique_abbrev() in that
|
/* This is different from find_unique_abbrev() in that
|
||||||
* it needs to deal with 0{40} SHA1.
|
* it stuffs the result with dots for alignment.
|
||||||
*/
|
*/
|
||||||
const char *diff_unique_abbrev(const unsigned char *sha1, int len)
|
const char *diff_unique_abbrev(const unsigned char *sha1, int len)
|
||||||
{
|
{
|
||||||
@ -966,16 +973,8 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len)
|
|||||||
return sha1_to_hex(sha1);
|
return sha1_to_hex(sha1);
|
||||||
|
|
||||||
abbrev = find_unique_abbrev(sha1, len);
|
abbrev = find_unique_abbrev(sha1, len);
|
||||||
if (!abbrev) {
|
if (!abbrev)
|
||||||
if (!memcmp(sha1, null_sha1, 20)) {
|
|
||||||
char *buf = sha1_to_hex(null_sha1);
|
|
||||||
if (len < 37)
|
|
||||||
strcpy(buf + len, "...");
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return sha1_to_hex(sha1);
|
return sha1_to_hex(sha1);
|
||||||
}
|
|
||||||
abblen = strlen(abbrev);
|
abblen = strlen(abbrev);
|
||||||
if (abblen < 37) {
|
if (abblen < 37) {
|
||||||
static char hex[41];
|
static char hex[41];
|
||||||
|
28
diff.h
28
diff.h
@ -13,6 +13,9 @@ struct tree_desc {
|
|||||||
unsigned long size;
|
unsigned long size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern void update_tree_entry(struct tree_desc *);
|
||||||
|
extern const unsigned char *tree_entry_extract(struct tree_desc *, const char **, unsigned int *);
|
||||||
|
|
||||||
struct diff_options;
|
struct diff_options;
|
||||||
|
|
||||||
typedef void (*change_fn_t)(struct diff_options *options,
|
typedef void (*change_fn_t)(struct diff_options *options,
|
||||||
@ -56,6 +59,28 @@ extern int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
|
|||||||
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
|
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
|
||||||
const char *base, struct diff_options *opt);
|
const char *base, struct diff_options *opt);
|
||||||
|
|
||||||
|
struct combine_diff_path {
|
||||||
|
struct combine_diff_path *next;
|
||||||
|
int len;
|
||||||
|
char *path;
|
||||||
|
unsigned int mode;
|
||||||
|
unsigned char sha1[20];
|
||||||
|
struct combine_diff_parent {
|
||||||
|
char status;
|
||||||
|
unsigned int mode;
|
||||||
|
unsigned char sha1[20];
|
||||||
|
} parent[FLEX_ARRAY];
|
||||||
|
};
|
||||||
|
#define combine_diff_path_size(n, l) \
|
||||||
|
(sizeof(struct combine_diff_path) + \
|
||||||
|
sizeof(struct combine_diff_parent) * (n) + (l) + 1)
|
||||||
|
|
||||||
|
extern int show_combined_diff(struct combine_diff_path *elem, int num_parent,
|
||||||
|
int dense, const char *header,
|
||||||
|
struct diff_options *);
|
||||||
|
|
||||||
|
extern const char *diff_tree_combined_merge(const unsigned char *sha1, const char *, int, struct diff_options *opt);
|
||||||
|
|
||||||
extern void diff_addremove(struct diff_options *,
|
extern void diff_addremove(struct diff_options *,
|
||||||
int addremove,
|
int addremove,
|
||||||
unsigned mode,
|
unsigned mode,
|
||||||
@ -88,9 +113,6 @@ extern int diff_setup_done(struct diff_options *);
|
|||||||
|
|
||||||
#define DIFF_PICKAXE_ALL 1
|
#define DIFF_PICKAXE_ALL 1
|
||||||
|
|
||||||
#define DIFF_DEFAULT_INDEX_ABBREV 7 /* hex digits */
|
|
||||||
#define DIFF_DEFAULT_ABBREV 7 /* hex digits */
|
|
||||||
|
|
||||||
extern void diffcore_std(struct diff_options *);
|
extern void diffcore_std(struct diff_options *);
|
||||||
|
|
||||||
extern void diffcore_std_no_resolve(struct diff_options *);
|
extern void diffcore_std_no_resolve(struct diff_options *);
|
||||||
|
@ -105,9 +105,13 @@ static int compare_pair_order(const void *a_, const void *b_)
|
|||||||
void diffcore_order(const char *orderfile)
|
void diffcore_order(const char *orderfile)
|
||||||
{
|
{
|
||||||
struct diff_queue_struct *q = &diff_queued_diff;
|
struct diff_queue_struct *q = &diff_queued_diff;
|
||||||
struct pair_order *o = xmalloc(sizeof(*o) * q->nr);
|
struct pair_order *o;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!q->nr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
o = xmalloc(sizeof(*o) * q->nr);
|
||||||
prepare_order(orderfile);
|
prepare_order(orderfile);
|
||||||
for (i = 0; i < q->nr; i++) {
|
for (i = 0; i < q->nr; i++) {
|
||||||
o[i].pair = q->queue[i];
|
o[i].pair = q->queue[i];
|
||||||
|
@ -48,6 +48,9 @@ void diffcore_pathspec(const char **pathspec)
|
|||||||
for (i = 0; pathspec[i]; i++)
|
for (i = 0; pathspec[i]; i++)
|
||||||
;
|
;
|
||||||
speccnt = i;
|
speccnt = i;
|
||||||
|
if (!speccnt)
|
||||||
|
return;
|
||||||
|
|
||||||
spec = xmalloc(sizeof(*spec) * speccnt);
|
spec = xmalloc(sizeof(*spec) * speccnt);
|
||||||
for (i = 0; pathspec[i]; i++) {
|
for (i = 0; pathspec[i]; i++) {
|
||||||
spec[i].spec = pathspec[i];
|
spec[i].spec = pathspec[i];
|
||||||
|
@ -282,7 +282,7 @@ void diffcore_rename(struct diff_options *options)
|
|||||||
else if (detect_rename == DIFF_DETECT_COPY)
|
else if (detect_rename == DIFF_DETECT_COPY)
|
||||||
register_rename_src(p->one, 1);
|
register_rename_src(p->one, 1);
|
||||||
}
|
}
|
||||||
if (rename_dst_nr == 0 ||
|
if (rename_dst_nr == 0 || rename_src_nr == 0 ||
|
||||||
(0 < rename_limit && rename_limit < rename_dst_nr))
|
(0 < rename_limit && rename_limit < rename_dst_nr))
|
||||||
goto cleanup; /* nothing to do */
|
goto cleanup; /* nothing to do */
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user