Merge branch 'master' into js/fmt-patch

* master: (109 commits)
  t1300-repo-config: two new config parsing tests.
  Another config file parsing fix.
  update-index: plug memory leak from prefix_path()
  checkout-index: plug memory leak from prefix_path()
  update-index --unresolve: work from a subdirectory.
  pack-object: squelch eye-candy on non-tty
  core.prefersymlinkrefs: use symlinks for .git/HEAD
  repo-config: trim white-space before comment
  Fix for config file section parsing.
  Clarify git-cherry documentation.
  Update git-unpack-objects documentation.
  Fix up docs where "--" isn't displayed correctly.
  Several trivial documentation touch ups.
  git-svn 1.0.0
  git-svn: documentation updates
  delta: stricter constness
  Makefile: do not link rev-list any specially.
  builtin-push: --all and --tags _are_ explicit refspecs
  builtin-log/whatchanged/show: make them official.
  show-branch: omit uninteresting merges.
  ...
This commit is contained in:
Junio C Hamano 2006-05-06 14:42:08 -07:00
commit c66b6c067e
90 changed files with 6077 additions and 3202 deletions

View File

@ -79,7 +79,7 @@ clean:
asciidoc -b xhtml11 -d manpage -f asciidoc.conf $< asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<
%.1 %.7 : %.xml %.1 %.7 : %.xml
xmlto man $< xmlto -m callouts.xsl man $<
%.xml : %.txt %.xml : %.txt
asciidoc -b docbook -d manpage -f asciidoc.conf $< asciidoc -b docbook -d manpage -f asciidoc.conf $<

View File

@ -0,0 +1,16 @@
<!-- callout.xsl: converts asciidoc callouts to man page format -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="co">
<xsl:value-of select="concat('\fB(',substring-after(@id,'-'),')\fR')"/>
</xsl:template>
<xsl:template match="calloutlist">
<xsl:text>.sp&#10;</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="callout">
<xsl:value-of select="concat('\fB',substring-after(@arearefs,'-'),'. \fR')"/>
<xsl:apply-templates/>
<xsl:text>.br&#10;</xsl:text>
</xsl:template>
</xsl:stylesheet>

183
Documentation/config.txt Normal file
View File

@ -0,0 +1,183 @@
CONFIGURATION FILE
------------------
The git configuration file contains a number of variables that affect
the git commands behaviour. They can be used by both the git plumbing
and the porcelains. The variables are divided to sections, where
in the fully qualified variable name the variable itself is the last
dot-separated segment and the section name is everything before the last
dot. The variable names are case-insensitive and only alphanumeric
characters are allowed. Some variables may appear multiple times.
The syntax is fairly flexible and permissive; whitespaces are mostly
ignored. The '#' and ';' characters begin commends to the end of line,
blank lines are ignored, lines containing strings enclosed in square
brackets start sections and all the other lines are recognized
as setting variables, in the form 'name = value'. If there is no equal
sign on the line, the entire line is taken as 'name' and the variable
is recognized as boolean "true". String values may be entirely or partially
enclosed in double quotes; some variables may require special value format.
Example
~~~~~~~
# Core variables
[core]
; Don't trust file modes
filemode = false
# Our diff algorithm
[diff]
external = "/usr/local/bin/gnu-diff -u"
renames = true
Variables
~~~~~~~~~
Note that this list is non-comprehensive and not necessarily complete.
For command-specific variables, you will find more detailed description
in the appropriate manual page. You will find description of non-core
porcelain configuration variables in the respective porcelain documentation.
core.fileMode::
If false, the executable bit differences between the index and
the working copy are ignored; useful on broken filesystems like FAT.
See gitlink:git-update-index[1]. True by default.
core.gitProxy::
A "proxy command" to execute (as 'command host port') instead
of establishing direct connection to the remote server when
using the git protocol for fetching. If the variable value is
in the "COMMAND for DOMAIN" format, the command is applied only
on hostnames ending with the specified domain string. This variable
may be set multiple times and is matched in the given order;
the first match wins.
Can be overriden by the 'GIT_PROXY_COMMAND' environment variable
(which always applies universally, without the special "for"
handling).
core.ignoreStat::
The working copy files are assumed to stay unchanged until you
mark them otherwise manually - Git will not detect the file changes
by lstat() calls. This is useful on systems where those are very
slow, such as Microsoft Windows. See gitlink:git-update-index[1].
False by default.
core.preferSymlinkRefs::
Instead of the default "symref" format for HEAD
and other symbolic reference files, use symbolic links.
This is sometimes needed to work with old scripts that
expect HEAD to be a symbolic link.
core.repositoryFormatVersion::
Internal variable identifying the repository format and layout
version.
core.sharedRepository::
If true, the repository is made shareable between several users
in a group (making sure all the files and objects are group-writable).
See gitlink:git-init-db[1]. False by default.
core.warnAmbiguousRefs::
If true, git will warn you if the ref name you passed it is ambiguous
and might match multiple refs in the .git/refs/ tree. True by default.
apply.whitespace::
Tells `git-apply` how to handle whitespaces, in the same way
as the '--whitespace' option. See gitlink:git-apply[1].
diff.renameLimit::
The number of files to consider when performing the copy/rename
detection; equivalent to the git diff option '-l'.
format.headers::
Additional email headers to include in a patch to be submitted
by mail. See gitlink:git-format-patch[1].
gitcvs.enabled::
Whether the cvs pserver interface is enabled for this repository.
See gitlink:git-cvsserver[1].
gitcvs.logfile::
Path to a log file where the cvs pserver interface well... logs
various stuff. See gitlink:git-cvsserver[1].
http.sslVerify::
Whether to verify the SSL certificate when fetching or pushing
over HTTPS. Can be overriden by the 'GIT_SSL_NO_VERIFY' environment
variable.
http.sslCert::
File containing the SSL certificate when fetching or pushing
over HTTPS. Can be overriden by the 'GIT_SSL_CERT' environment
variable.
http.sslKey::
File containing the SSL private key when fetching or pushing
over HTTPS. Can be overriden by the 'GIT_SSL_KEY' environment
variable.
http.sslCAInfo::
File containing the certificates to verify the peer with when
fetching or pushing over HTTPS. Can be overriden by the
'GIT_SSL_CAINFO' environment variable.
http.sslCAPath::
Path containing files with the CA certificates to verify the peer
with when fetching or pushing over HTTPS. Can be overriden
by the 'GIT_SSL_CAPATH' environment variable.
http.maxRequests::
How many HTTP requests to launch in parallel. Can be overriden
by the 'GIT_HTTP_MAX_REQUESTS' environment variable. Default is 5.
http.lowSpeedLimit, http.lowSpeedTime::
If the HTTP transfer speed is less than 'http.lowSpeedLimit'
for longer than 'http.lowSpeedTime' seconds, the transfer is aborted.
Can be overriden by the 'GIT_HTTP_LOW_SPEED_LIMIT' and
'GIT_HTTP_LOW_SPEED_TIME' environment variables.
i18n.commitEncoding::
Character encoding the commit messages are stored in; git itself
does not care per se, but this information is necessary e.g. when
importing commits from emails or in the gitk graphical history
browser (and possibly at other places in the future or in other
porcelains). See e.g. gitlink:git-mailinfo[1]. Defaults to 'utf-8'.
merge.summary::
Whether to include summaries of merged commits in newly created
merge commit messages. False by default.
pull.octopus::
The default merge strategy to use when pulling multiple branches
at once.
pull.twohead::
The default merge strategy to use when pulling a single branch.
show.difftree::
The default gitlink:git-diff-tree[1] arguments to be used
for gitlink:git-show[1].
showbranch.default::
The default set of branches for gitlink:git-show-branch[1].
See gitlink:git-show-branch[1].
user.email::
Your email address to be recorded in any newly created commits.
Can be overriden by the 'GIT_AUTHOR_EMAIL' and 'GIT_COMMITTER_EMAIL'
environment variables. See gitlink:git-commit-tree[1].
user.name::
Your full name to be recorded in any newly created commits.
Can be overriden by the 'GIT_AUTHOR_NAME' and 'GIT_COMMITTER_NAME'
environment variables. See gitlink:git-commit-tree[1].
whatchanged.difftree::
The default gitlink:git-diff-tree[1] arguments to be used
for gitlink:git-whatchanged[1].
imap::
The configuration variables in the 'imap' section are described
in gitlink:git-imap-send[1].

View File

@ -61,7 +61,8 @@ $ git prune
$ git count-objects <2> $ git count-objects <2>
$ git repack <3> $ git repack <3>
$ git prune <4> $ git prune <4>
------------
+
<1> running without "--full" is usually cheap and assures the <1> running without "--full" is usually cheap and assures the
repository health reasonably well. repository health reasonably well.
<2> check how many loose objects there are and how much <2> check how many loose objects there are and how much
@ -69,17 +70,16 @@ diskspace is wasted by not repacking.
<3> without "-a" repacks incrementally. repacking every 4-5MB <3> without "-a" repacks incrementally. repacking every 4-5MB
of loose objects accumulation may be a good rule of thumb. of loose objects accumulation may be a good rule of thumb.
<4> after repack, prune removes the duplicate loose objects. <4> after repack, prune removes the duplicate loose objects.
------------
Repack a small project into single pack.:: Repack a small project into single pack.::
+ +
------------ ------------
$ git repack -a -d <1> $ git repack -a -d <1>
$ git prune $ git prune
------------
+
<1> pack all the objects reachable from the refs into one pack <1> pack all the objects reachable from the refs into one pack
and remove unneeded other packs and remove unneeded other packs
------------
Individual Developer (Standalone)[[Individual Developer (Standalone)]] Individual Developer (Standalone)[[Individual Developer (Standalone)]]
@ -129,10 +129,10 @@ $ git-init-db
$ git add . <1> $ git add . <1>
$ git commit -m 'import of frotz source tree.' $ git commit -m 'import of frotz source tree.'
$ git tag v2.43 <2> $ git tag v2.43 <2>
------------
+
<1> add everything under the current directory. <1> add everything under the current directory.
<2> make a lightweight, unannotated tag. <2> make a lightweight, unannotated tag.
------------
Create a topic branch and develop.:: Create a topic branch and develop.::
+ +
@ -153,7 +153,8 @@ $ git checkout master <9>
$ git pull . alsa-audio <10> $ git pull . alsa-audio <10>
$ git log --since='3 days ago' <11> $ git log --since='3 days ago' <11>
$ git log v2.43.. curses/ <12> $ git log v2.43.. curses/ <12>
------------
+
<1> create a new topic branch. <1> create a new topic branch.
<2> revert your botched changes in "curses/ux_audio_oss.c". <2> revert your botched changes in "curses/ux_audio_oss.c".
<3> you need to tell git if you added a new file; removal and <3> you need to tell git if you added a new file; removal and
@ -170,7 +171,6 @@ you originally wrote.
combined and include --max-count=10 (show 10 commits), --until='2005-12-10'. combined and include --max-count=10 (show 10 commits), --until='2005-12-10'.
<12> view only the changes that touch what's in curses/ <12> view only the changes that touch what's in curses/
directory, since v2.43 tag. directory, since v2.43 tag.
------------
Individual Developer (Participant)[[Individual Developer (Participant)]] Individual Developer (Participant)[[Individual Developer (Participant)]]
@ -208,7 +208,8 @@ $ git pull git://git.kernel.org/pub/.../jgarzik/libata-dev.git ALL <5>
$ git reset --hard ORIG_HEAD <6> $ git reset --hard ORIG_HEAD <6>
$ git prune <7> $ git prune <7>
$ git fetch --tags <8> $ git fetch --tags <8>
------------
+
<1> repeat as needed. <1> repeat as needed.
<2> extract patches from your branch for e-mail submission. <2> extract patches from your branch for e-mail submission.
<3> "pull" fetches from "origin" by default and merges into the <3> "pull" fetches from "origin" by default and merges into the
@ -221,7 +222,6 @@ area we are interested in.
<7> garbage collect leftover objects from reverted pull. <7> garbage collect leftover objects from reverted pull.
<8> from time to time, obtain official tags from the "origin" <8> from time to time, obtain official tags from the "origin"
and store them under .git/refs/tags/. and store them under .git/refs/tags/.
------------
Push into another repository.:: Push into another repository.::
@ -239,7 +239,8 @@ satellite$ git push origin <4>
mothership$ cd frotz mothership$ cd frotz
mothership$ git checkout master mothership$ git checkout master
mothership$ git pull . satellite <5> mothership$ git pull . satellite <5>
------------
+
<1> mothership machine has a frotz repository under your home <1> mothership machine has a frotz repository under your home
directory; clone from it to start a repository on the satellite directory; clone from it to start a repository on the satellite
machine. machine.
@ -252,7 +253,6 @@ to local "origin" branch.
mothership machine. You could use this as a back-up method. mothership machine. You could use this as a back-up method.
<5> on mothership machine, merge the work done on the satellite <5> on mothership machine, merge the work done on the satellite
machine into the master branch. machine into the master branch.
------------
Branch off of a specific tag.:: Branch off of a specific tag.::
+ +
@ -262,12 +262,12 @@ $ edit/compile/test; git commit -a
$ git checkout master $ git checkout master
$ git format-patch -k -m --stdout v2.6.14..private2.6.14 | $ git format-patch -k -m --stdout v2.6.14..private2.6.14 |
git am -3 -k <2> git am -3 -k <2>
------------
+
<1> create a private branch based on a well known (but somewhat behind) <1> create a private branch based on a well known (but somewhat behind)
tag. tag.
<2> forward port all changes in private2.6.14 branch to master branch <2> forward port all changes in private2.6.14 branch to master branch
without a formal "merging". without a formal "merging".
------------
Integrator[[Integrator]] Integrator[[Integrator]]
@ -317,7 +317,8 @@ $ git tag -s -m 'GIT 0.99.9x' v0.99.9x <10>
$ git fetch ko && git show-branch master maint 'tags/ko-*' <11> $ git fetch ko && git show-branch master maint 'tags/ko-*' <11>
$ git push ko <12> $ git push ko <12>
$ git push ko v0.99.9x <13> $ git push ko v0.99.9x <13>
------------
+
<1> see what I was in the middle of doing, if any. <1> see what I was in the middle of doing, if any.
<2> see what topic branches I have and think about how ready <2> see what topic branches I have and think about how ready
they are. they are.
@ -346,7 +347,6 @@ In the output from "git show-branch", "master" should have
everything "ko-master" has. everything "ko-master" has.
<12> push out the bleeding edge. <12> push out the bleeding edge.
<13> push the tag out, too. <13> push the tag out, too.
------------
Repository Administration[[Repository Administration]] Repository Administration[[Repository Administration]]
@ -367,7 +367,6 @@ example of managing a shared central repository.
Examples Examples
~~~~~~~~ ~~~~~~~~
Run git-daemon to serve /pub/scm from inetd.:: Run git-daemon to serve /pub/scm from inetd.::
+ +
------------ ------------
@ -388,13 +387,13 @@ cindy:x:1002:1002::/home/cindy:/usr/bin/git-shell
david:x:1003:1003::/home/david:/usr/bin/git-shell david:x:1003:1003::/home/david:/usr/bin/git-shell
$ grep git /etc/shells <2> $ grep git /etc/shells <2>
/usr/bin/git-shell /usr/bin/git-shell
------------
+
<1> log-in shell is set to /usr/bin/git-shell, which does not <1> log-in shell is set to /usr/bin/git-shell, which does not
allow anything but "git push" and "git pull". The users should allow anything but "git push" and "git pull". The users should
get an ssh access to the machine. get an ssh access to the machine.
<2> in many distributions /etc/shells needs to list what is used <2> in many distributions /etc/shells needs to list what is used
as the login shell. as the login shell.
------------
CVS-style shared repository.:: CVS-style shared repository.::
+ +
@ -419,7 +418,8 @@ $ cat info/allowed-users <4>
refs/heads/master alice\|cindy refs/heads/master alice\|cindy
refs/heads/doc-update bob refs/heads/doc-update bob
refs/tags/v[0-9]* david refs/tags/v[0-9]* david
------------
+
<1> place the developers into the same git group. <1> place the developers into the same git group.
<2> and make the shared repository writable by the group. <2> and make the shared repository writable by the group.
<3> use update-hook example by Carl from Documentation/howto/ <3> use update-hook example by Carl from Documentation/howto/
@ -427,7 +427,6 @@ for branch policy control.
<4> alice and cindy can push into master, only bob can push into doc-update. <4> alice and cindy can push into master, only bob can push into doc-update.
david is the release manager and is the only person who can david is the release manager and is the only person who can
create and push version tags. create and push version tags.
------------
HTTP server to support dumb protocol transfer.:: HTTP server to support dumb protocol transfer.::
+ +
@ -435,7 +434,7 @@ HTTP server to support dumb protocol transfer.::
dev$ git update-server-info <1> dev$ git update-server-info <1>
dev$ ftp user@isp.example.com <2> dev$ ftp user@isp.example.com <2>
ftp> cp -r .git /home/user/myproject.git ftp> cp -r .git /home/user/myproject.git
------------
+
<1> make sure your info/refs and objects/info/packs are up-to-date <1> make sure your info/refs and objects/info/packs are up-to-date
<2> upload to public HTTP server hosted by your ISP. <2> upload to public HTTP server hosted by your ISP.
------------

View File

@ -26,7 +26,7 @@ OPTIONS
-v:: -v::
Be verbose. Be verbose.
--:: \--::
This option can be used to separate command-line options from This option can be used to separate command-line options from
the list of files, (useful when filenames might be mistaken the list of files, (useful when filenames might be mistaken
for command-line options). for command-line options).

View File

@ -3,22 +3,27 @@ git-branch(1)
NAME NAME
---- ----
git-branch - Create a new branch, or remove an old one git-branch - List, create, or delete branches.
SYNOPSIS SYNOPSIS
-------- --------
[verse] [verse]
'git-branch' [[-f] <branchname> [<start-point>]] 'git-branch' [-r]
'git-branch' (-d | -D) <branchname> 'git-branch' [-f] <branchname> [<start-point>]
'git-branch' (-d | -D) <branchname>...
DESCRIPTION DESCRIPTION
----------- -----------
If no argument is provided, show available branches and mark current With no arguments given (or just `-r`) a list of available branches
branch with star. Otherwise, create a new branch of name <branchname>. will be shown, the current branch will be highlighted with an asterisk.
If a starting point is also specified, that will be where the branch is
created, otherwise it will be created at the current HEAD.
With a `-d` or `-D` option, `<branchname>` will be deleted. In its second form, a new branch named <branchname> will be created.
It will start out with a head equal to the one given as <start-point>.
If no <start-point> is given, the branch will be created with a head
equal to that of the currently checked out branch.
With a `-d` or `-D` option, `<branchname>` will be deleted. You may
specify more than one branch for deletion.
OPTIONS OPTIONS
@ -30,18 +35,24 @@ OPTIONS
Delete a branch irrespective of its index status. Delete a branch irrespective of its index status.
-f:: -f::
Force a reset of <branchname> to <start-point> (or current head). Force the creation of a new branch even if it means deleting
a branch that already exists with the same name.
-r::
List only the "remote" branches.
<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 The new branch will be created with a HEAD equal to this. It may
option has no meaning with -d and -D. be given as a branch name, a commit-id, or a tag. If this option
is omitted, the current branch is assumed.
Examples Examples
~~~~~~~~ --------
Start development off of a known tag:: Start development off of a known tag::
+ +
@ -50,9 +61,10 @@ $ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6
$ cd my2.6 $ cd my2.6
$ git branch my2.6.14 v2.6.14 <1> $ git branch my2.6.14 v2.6.14 <1>
$ git checkout my2.6.14 $ git checkout my2.6.14
<1> These two steps are the same as "checkout -b my2.6.14 v2.6.14".
------------ ------------
+
<1> This step and the next one could be combined into a single step with
"checkout -b my2.6.14 v2.6.14".
Delete unneeded branch:: Delete unneeded branch::
+ +
@ -60,10 +72,19 @@ Delete unneeded branch::
$ git clone git://git.kernel.org/.../git.git my.git $ git clone git://git.kernel.org/.../git.git my.git
$ cd my.git $ cd my.git
$ git branch -D todo <1> $ git branch -D todo <1>
------------
+
<1> delete todo branch even if the "master" branch does not have all <1> delete todo branch even if the "master" branch does not have all
commits from todo branch. commits from todo branch.
------------
Notes
-----
If you are creating a branch that you want to immediately checkout, it's
easier to use the git checkout command with its `-b` option to create
a branch and check it out with a single command.
Author Author
------ ------

View File

@ -63,7 +63,7 @@ OPTIONS
Only meaningful with `--stdin`; paths are separated with Only meaningful with `--stdin`; paths are separated with
NUL character instead of LF. NUL character instead of LF.
--:: \--::
Do not interpret any more arguments as options. Do not interpret any more arguments as options.
The order of the flags used to matter, but not anymore. The order of the flags used to matter, but not anymore.

View File

@ -70,15 +70,15 @@ $ git checkout master <1>
$ git checkout master~2 Makefile <2> $ git checkout master~2 Makefile <2>
$ rm -f hello.c $ rm -f hello.c
$ git checkout hello.c <3> $ git checkout hello.c <3>
<1> switch branch
<2> take out a file out of other commit
<3> or "git checkout -- hello.c", as in the next example.
------------ ------------
+ +
If you have an unfortunate branch that is named `hello.c`, the <1> switch branch
last step above would be confused as an instruction to switch to <2> take out a file out of other commit
that branch. You should instead write: <3> restore hello.c from HEAD of current branch
+
If you have an unfortunate branch that is named `hello.c`, this
step would be confused as an instruction to switch to that branch.
You should instead write:
+ +
------------ ------------
$ git checkout -- hello.c $ git checkout -- hello.c

View File

@ -11,11 +11,20 @@ SYNOPSIS
DESCRIPTION DESCRIPTION
----------- -----------
Each commit between the fork-point and <head> is examined, and compared against The changeset (or "diff") of each commit between the fork-point and <head>
the change each commit between the fork-point and <upstream> introduces. is compared against each commit between the fork-point and <upstream>.
Commits already included in upstream are prefixed with '-' (meaning "drop from
my local pull"), while commits missing from upstream are prefixed with '+' Every commit with a changeset that doesn't exist in the other branch
(meaning "add to the updated upstream"). has its id (sha1) reported, prefixed by a symbol. Those existing only
in the <upstream> branch are prefixed with a minus (-) sign, and those
that only exist in the <head> branch are prefixed with a plus (+) symbol.
Because git-cherry compares the changeset rather than the commit id
(sha1), you can use git-cherry to find out if a commit you made locally
has been applied <upstream> under a different commit id. For example,
this will happen if you're feeding patches <upstream> via email rather
than pushing or pulling commits directly.
OPTIONS OPTIONS
------- -------

View File

@ -101,7 +101,7 @@ OPTIONS
is not allowed. is not allowed.
Examples Examples
~~~~~~~~ --------
Clone from upstream:: Clone from upstream::
+ +

View File

@ -106,7 +106,7 @@ but can be used to amend a merge commit.
index and the latest commit does not match on the index and the latest commit does not match on the
specified paths to avoid confusion. specified paths to avoid confusion.
--:: \--::
Do not interpret any more arguments as options. Do not interpret any more arguments as options.
<file>...:: <file>...::

View File

@ -7,13 +7,23 @@ git-count-objects - Reports on unpacked objects
SYNOPSIS SYNOPSIS
-------- --------
'git-count-objects' 'git-count-objects' [-v]
DESCRIPTION DESCRIPTION
----------- -----------
This counts the number of unpacked object files and disk space consumed by This counts the number of unpacked object files and disk space consumed by
them, to help you decide when it is a good time to repack. them, to help you decide when it is a good time to repack.
OPTIONS
-------
-v::
In addition to the number of loose objects and disk
space consumed, it reports the number of in-pack
objects, and number of objects that can be removed by
running `git-prune-packed`.
Author Author
------ ------
Written by Junio C Hamano <junkio@cox.net> Written by Junio C Hamano <junkio@cox.net>

View File

@ -92,7 +92,7 @@ separated with a single space are given.
Furthermore, it lists only files which were modified Furthermore, it lists only files which were modified
from all parents. from all parents.
-cc:: --cc::
This flag changes the way a merge commit patch is displayed, This flag changes the way a merge commit patch is displayed,
in a similar way to the '-c' option. It implies the '-c' in a similar way to the '-c' option. It implies the '-c'
and '-p' options and further compresses the patch output and '-p' options and further compresses the patch output

View File

@ -49,13 +49,13 @@ Various ways to check your working tree::
$ git diff <1> $ git diff <1>
$ git diff --cached <2> $ git diff --cached <2>
$ git diff HEAD <3> $ git diff HEAD <3>
------------
+
<1> changes in the working tree since your last git-update-index. <1> changes in the working tree since your last git-update-index.
<2> changes between the index and your last commit; what you <2> changes between the index and your last commit; what you
would be committing if you run "git commit" without "-a" option. would be committing if you run "git commit" without "-a" option.
<3> changes in the working tree since your last commit; what you <3> changes in the working tree since your last commit; what you
would be committing if you run "git commit -a" would be committing if you run "git commit -a"
------------
Comparing with arbitrary commits:: Comparing with arbitrary commits::
+ +
@ -63,14 +63,14 @@ Comparing with arbitrary commits::
$ git diff test <1> $ git diff test <1>
$ git diff HEAD -- ./test <2> $ git diff HEAD -- ./test <2>
$ git diff HEAD^ HEAD <3> $ 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 current 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.
------------
Limiting the diff output:: Limiting the diff output::
@ -79,7 +79,8 @@ Limiting the diff output::
$ git diff --diff-filter=MRC <1> $ git diff --diff-filter=MRC <1>
$ git diff --name-status -r <2> $ git diff --name-status -r <2>
$ git diff arch/i386 include/asm-i386 <3> $ git diff arch/i386 include/asm-i386 <3>
------------
+
<1> show only modification, rename and copy, but not addition <1> show only modification, rename and copy, but not addition
nor deletion. nor deletion.
<2> show only names and the nature of change, but not actual <2> show only names and the nature of change, but not actual
@ -88,18 +89,17 @@ which in turn also disables recursive behaviour, so without -r
you would only see the directory name if there is a change in a you would only see the directory name if there is a change in a
file in a subdirectory. file in a subdirectory.
<3> limit diff output to named subtrees. <3> limit diff output to named subtrees.
------------
Munging the diff output:: Munging the diff output::
+ +
------------ ------------
$ git diff --find-copies-harder -B -C <1> $ git diff --find-copies-harder -B -C <1>
$ git diff -R <2> $ git diff -R <2>
------------
+
<1> spend extra cycles to find renames, copies and complete <1> spend extra cycles to find renames, copies and complete
rewrites (very expensive). rewrites (very expensive).
<2> output diff in reverse. <2> output diff in reverse.
------------
Author Author

View File

@ -29,6 +29,7 @@ CONFIGURATION
git-imap-send requires the following values in the repository git-imap-send requires the following values in the repository
configuration file (shown with examples): configuration file (shown with examples):
..........................
[imap] [imap]
Folder = "INBOX.Drafts" Folder = "INBOX.Drafts"
@ -38,8 +39,9 @@ configuration file (shown with examples):
[imap] [imap]
Host = imap.server.com Host = imap.server.com
User = bob User = bob
Password = pwd Pass = pwd
Port = 143 Port = 143
..........................
BUGS BUGS

View File

@ -62,10 +62,10 @@ Start a new git repository for an existing code base::
$ cd /path/to/my/codebase $ cd /path/to/my/codebase
$ git-init-db <1> $ git-init-db <1>
$ git-add . <2> $ git-add . <2>
----------------
+
<1> prepare /path/to/my/codebase/.git directory <1> prepare /path/to/my/codebase/.git directory
<2> add all existing file to the index <2> add all existing file to the index
----------------
Author Author

View File

@ -14,13 +14,12 @@ DESCRIPTION
----------- -----------
Shows the commit logs. Shows the commit logs.
The command takes options applicable to the gitlink::git-rev-list[1] The command takes options applicable to the gitlink:git-rev-list[1]
command to control what is shown and how, and options applicable to command to control what is shown and how, and options applicable to
the gitlink::git-diff-tree[1] commands to control how the change the gitlink:git-diff-tree[1] commands to control how the change
each commit introduces are shown. each commit introduces are shown.
This manual page describes only the most frequently used This manual page describes only the most frequently used options.
options.
OPTIONS OPTIONS
@ -52,7 +51,7 @@ git log v2.6.12.. include/scsi drivers/scsi::
Show all commits since version 'v2.6.12' that changed any file Show all commits since version 'v2.6.12' that changed any file
in the include/scsi or drivers/scsi subdirectories in the include/scsi or drivers/scsi subdirectories
git log --since="2 weeks ago" -- gitk:: git log --since="2 weeks ago" \-- gitk::
Show the changes during the last two weeks to the file 'gitk'. Show the changes during the last two weeks to the file 'gitk'.
The "--" is necessary to avoid confusion with the *branch* named The "--" is necessary to avoid confusion with the *branch* named

View File

@ -106,7 +106,7 @@ OPTIONS
lines, show only handful hexdigits prefix. lines, show only handful hexdigits prefix.
Non default number of digits can be specified with --abbrev=<n>. Non default number of digits can be specified with --abbrev=<n>.
--:: \--::
Do not interpret any more arguments as options. Do not interpret any more arguments as options.
<file>:: <file>::

View File

@ -8,7 +8,7 @@ git-merge-index - Runs a merge for files needing merging
SYNOPSIS SYNOPSIS
-------- --------
'git-merge-index' [-o] [-q] <merge-program> (-a | -- | <file>\*) 'git-merge-index' [-o] [-q] <merge-program> (-a | \-- | <file>\*)
DESCRIPTION DESCRIPTION
----------- -----------
@ -19,7 +19,7 @@ files are passed as arguments 5, 6 and 7.
OPTIONS OPTIONS
------- -------
--:: \--::
Do not interpret any more arguments as options. Do not interpret any more arguments as options.
-a:: -a::

View File

@ -41,6 +41,7 @@ Enter git-name-rev:
------------ ------------
% git name-rev 33db5f4d9027a10e477ccf054b2c1ab94f74c85a % git name-rev 33db5f4d9027a10e477ccf054b2c1ab94f74c85a
33db5f4d9027a10e477ccf054b2c1ab94f74c85a tags/v0.99^0~940
------------ ------------
Now you are wiser, because you know that it happened 940 revisions before v0.99. Now you are wiser, because you know that it happened 940 revisions before v0.99.

View File

@ -28,7 +28,7 @@ OPTIONS
Do not remove anything; just report what it would Do not remove anything; just report what it would
remove. remove.
--:: \--::
Do not interpret any more arguments as options. Do not interpret any more arguments as options.
<head>...:: <head>...::

View File

@ -3,38 +3,54 @@ git-rebase(1)
NAME NAME
---- ----
git-rebase - Rebase local commits to new upstream head git-rebase - Rebase local commits to a new head
SYNOPSIS SYNOPSIS
-------- --------
'git-rebase' [--onto <newbase>] <upstream> [<branch>] 'git-rebase' [--onto <newbase>] <upstream> [<branch>]
'git-rebase' --continue
'git-rebase' --abort
DESCRIPTION DESCRIPTION
----------- -----------
git-rebase applies to <upstream> (or optionally to <newbase>) commits git-rebase replaces <branch> with a new branch of the same name. When
from <branch> that do not appear in <upstream>. When <branch> is not the --onto option is provided the new branch starts out with a HEAD equal
specified it defaults to the current branch (HEAD). to <newbase>, otherwise it is equal to <upstream>. It then attempts to
create a new commit for each commit from the original <branch> that does
not exist in the <upstream> branch.
When git-rebase is complete, <branch> will be updated to point to the It is possible that a merge failure will prevent this process from being
newly created line of commit objects, so the previous line will not be completely automatic. You will have to resolve any such merge failure
accessible unless there are other references to it already. and run `git rebase --continue`. If you can not resolve the merge
failure, running `git rebase --abort` will restore the original <branch>
and remove the working files found in the .dotest directory.
Note that if <branch> is not specified on the command line, the currently
checked out branch is used.
Assume the following history exists and the current branch is "topic": Assume the following history exists and the current branch is "topic":
------------
A---B---C topic A---B---C topic
/ /
D---E---F---G master D---E---F---G master
------------
From this point, the result of either of the following commands: From this point, the result of either of the following commands:
git-rebase master git-rebase master
git-rebase master topic git-rebase master topic
would be: would be:
------------
A'--B'--C' topic A'--B'--C' topic
/ /
D---E---F---G master D---E---F---G master
------------
While, starting from the same point, the result of either of the following While, starting from the same point, the result of either of the following
commands: commands:
@ -44,21 +60,33 @@ commands:
would be: would be:
------------
A'--B'--C' topic A'--B'--C' topic
/ /
D---E---F---G master D---E---F---G master
------------
In case of conflict, git-rebase will stop at the first problematic commit In case of conflict, git-rebase will stop at the first problematic commit
and leave conflict markers in the tree. After resolving the conflict manually and leave conflict markers in the tree. You can use git diff to locate
and updating the index with the desired resolution, you can continue the the markers (<<<<<<) and make edits to resolve the conflict. For each
rebasing process with file you edit, you need to tell git that the conflict has been resolved,
typically this would be done with
git update-index <filename>
After resolving the conflict manually and updating the index with the
desired resolution, you can continue the rebasing process with
git rebase --continue
git am --resolved --3way
Alternatively, you can undo the git-rebase with Alternatively, you can undo the git-rebase with
git reset --hard ORIG_HEAD
rm -r .dotest git rebase --abort
OPTIONS OPTIONS
------- -------
@ -73,6 +101,28 @@ OPTIONS
<branch>:: <branch>::
Working branch; defaults to HEAD. Working branch; defaults to HEAD.
--continue::
Restart the rebasing process after having resolved a merge conflict.
--abort::
Restore the original branch and abort the rebase operation.
NOTES
-----
When you rebase a branch, you are changing its history in a way that
will cause problems for anyone who already has a copy of the branch
in their repository and tries to pull updates from you. You should
understand the implications of using 'git rebase' on a repository that
you share.
When the git rebase command is run, it will first execute a "pre-rebase"
hook if one exists. You can use this hook to do sanity checks and
reject the rebase if it isn't appropriate. Please see the template
pre-rebase hook script for an example.
You must be in the top directory of your project to start (or continue)
a rebase. Upon completion, <branch> will be the current branch.
Author Author
------ ------
Written by Junio C Hamano <junkio@cox.net> Written by Junio C Hamano <junkio@cox.net>

View File

@ -38,6 +38,7 @@ OPTIONS
-d:: -d::
After packing, if the newly created packs make some After packing, if the newly created packs make some
existing packs redundant, remove the redundant packs. existing packs redundant, remove the redundant packs.
Also runs gitlink:git-prune-packed[1].
-l:: -l::
Pass the `--local` option to `git pack-objects`, see Pass the `--local` option to `git pack-objects`, see

View File

@ -15,6 +15,7 @@ SYNOPSIS
'git-repo-config' [type] --get-all name [value_regex] 'git-repo-config' [type] --get-all name [value_regex]
'git-repo-config' [type] --unset name [value_regex] 'git-repo-config' [type] --unset name [value_regex]
'git-repo-config' [type] --unset-all name [value_regex] 'git-repo-config' [type] --unset-all name [value_regex]
'git-repo-config' -l | --list
DESCRIPTION DESCRIPTION
----------- -----------
@ -33,10 +34,10 @@ 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, a "true" or "false" string for bool). If no type specifier is passed,
no checks or transformations are performed on the value. no checks or transformations are performed on the value.
This command will fail if This command will fail if:
. .git/config is invalid, . The .git/config file is invalid,
. .git/config can not be written to, . Can not write to .git/config,
. no section was provided, . no section was provided,
. the section or key is invalid, . the section or key is invalid,
. you try to unset an option which does not exist, or . you try to unset an option which does not exist, or
@ -48,7 +49,7 @@ OPTIONS
--replace-all:: --replace-all::
Default behaviour is to replace at most one line. This replaces Default behaviour is to replace at most one line. This replaces
all lines matching the key (and optionally the value_regex) all lines matching the key (and optionally the value_regex).
--get:: --get::
Get the value for a given key (optionally filtered by a regex Get the value for a given key (optionally filtered by a regex
@ -58,12 +59,18 @@ OPTIONS
Like get, but does not fail if the number of values for the key Like get, but does not fail if the number of values for the key
is not exactly one. is not exactly one.
--get-regexp::
Like --get-all, but interprets the name as a regular expression.
--unset:: --unset::
Remove the line matching the key from .git/config. Remove the line matching the key from .git/config.
--unset-all:: --unset-all::
Remove all matching lines from .git/config. Remove all matching lines from .git/config.
-l, --list::
List all variables set in .git/config.
EXAMPLE EXAMPLE
------- -------
@ -87,11 +94,11 @@ Given a .git/config like this:
renames = true renames = true
; Proxy settings ; Proxy settings
[proxy] [core]
command="ssh" for "ssh://kernel.org/" gitproxy="ssh" for "ssh://kernel.org/"
command="proxy-command" for kernel.org gitproxy="proxy-command" for kernel.org
command="myprotocol-command" for "my://" gitproxy="myprotocol-command" for "my://"
command=default-proxy ; for all the rest gitproxy=default-proxy ; for all the rest
you can set the filemode to true with you can set the filemode to true with
@ -104,7 +111,7 @@ to what URL they apply. Here is how to change the entry for kernel.org
to "ssh". to "ssh".
------------ ------------
% git repo-config proxy.command '"ssh" for kernel.org' 'for kernel.org$' % git repo-config core.gitproxy '"ssh" for kernel.org' 'for kernel.org$'
------------ ------------
This makes sure that only the key/value pair for kernel.org is replaced. This makes sure that only the key/value pair for kernel.org is replaced.
@ -115,7 +122,7 @@ To delete the entry for renames, do
% git repo-config --unset diff.renames % git repo-config --unset diff.renames
------------ ------------
If you want to delete an entry for a multivar (like proxy.command above), If you want to delete an entry for a multivar (like core.gitproxy above),
you have to provide a regex matching the value of exactly one line. you have to provide a regex matching the value of exactly one line.
To query the value for a given key, do To query the value for a given key, do
@ -133,27 +140,27 @@ or
or, to query a multivar: or, to query a multivar:
------------ ------------
% git repo-config --get proxy.command "for kernel.org$" % git repo-config --get core.gitproxy "for kernel.org$"
------------ ------------
If you want to know all the values for a multivar, do: If you want to know all the values for a multivar, do:
------------ ------------
% git repo-config --get-all proxy.command % git repo-config --get-all core.gitproxy
------------ ------------
If you like to live dangerous, you can replace *all* proxy.commands by a If you like to live dangerous, you can replace *all* core.gitproxy by a
new one with new one with
------------ ------------
% git repo-config --replace-all proxy.command ssh % git repo-config --replace-all core.gitproxy ssh
------------ ------------
However, if you really only want to replace the line for the default proxy, However, if you really only want to replace the line for the default proxy,
i.e. the one without a "for ..." postfix, do something like this: i.e. the one without a "for ..." postfix, do something like this:
------------ ------------
% git repo-config proxy.command ssh '! for ' % git repo-config core.gitproxy ssh '! for '
------------ ------------
To actually match only values with an exclamation mark, you have to To actually match only values with an exclamation mark, you have to
@ -163,13 +170,16 @@ To actually match only values with an exclamation mark, you have to
------------ ------------
include::config.txt[]
Author Author
------ ------
Written by Johannes Schindelin <Johannes.Schindelin@gmx.de> Written by Johannes Schindelin <Johannes.Schindelin@gmx.de>
Documentation Documentation
-------------- --------------
Documentation by Johannes Schindelin. Documentation by Johannes Schindelin, Petr Baudis and the git-list <git@vger.kernel.org>.
GIT GIT
--- ---

View File

@ -43,7 +43,7 @@ OPTIONS
Commit to make the current HEAD. Commit to make the current HEAD.
Examples Examples
~~~~~~~~ --------
Undo a commit and redo:: Undo a commit and redo::
+ +
@ -52,7 +52,8 @@ $ git commit ...
$ git reset --soft HEAD^ <1> $ git reset --soft HEAD^ <1>
$ edit <2> $ edit <2>
$ git commit -a -c ORIG_HEAD <3> $ git commit -a -c ORIG_HEAD <3>
------------
+
<1> This is most often done when you remembered what you <1> This is most often done when you remembered what you
just committed is incomplete, or you misspelled your commit just committed is incomplete, or you misspelled your commit
message, or both. Leaves working tree as it was before "reset". message, or both. Leaves working tree as it was before "reset".
@ -60,18 +61,17 @@ message, or both. Leaves working tree as it was before "reset".
<3> "reset" copies the old head to .git/ORIG_HEAD; redo the <3> "reset" copies the old head to .git/ORIG_HEAD; redo the
commit by starting with its log message. If you do not need to commit by starting with its log message. If you do not need to
edit the message further, you can give -C option instead. edit the message further, you can give -C option instead.
------------
Undo commits permanently:: Undo commits permanently::
+ +
------------ ------------
$ git commit ... $ git commit ...
$ git reset --hard HEAD~3 <1> $ git reset --hard HEAD~3 <1>
------------
+
<1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad <1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad
and you do not want to ever see them again. Do *not* do this if and you do not want to ever see them again. Do *not* do this if
you have already given these commits to somebody else. you have already given these commits to somebody else.
------------
Undo a commit, making it a topic branch:: Undo a commit, making it a topic branch::
+ +
@ -79,14 +79,14 @@ Undo a commit, making it a topic branch::
$ git branch topic/wip <1> $ git branch topic/wip <1>
$ git reset --hard HEAD~3 <2> $ git reset --hard HEAD~3 <2>
$ git checkout topic/wip <3> $ git checkout topic/wip <3>
------------
+
<1> You have made some commits, but realize they were premature <1> You have made some commits, but realize they were premature
to be in the "master" branch. You want to continue polishing to be in the "master" branch. You want to continue polishing
them in a topic branch, so create "topic/wip" branch off of the them in a topic branch, so create "topic/wip" branch off of the
current HEAD. current HEAD.
<2> Rewind the master branch to get rid of those three commits. <2> Rewind the master branch to get rid of those three commits.
<3> Switch to "topic/wip" branch and keep working. <3> Switch to "topic/wip" branch and keep working.
------------
Undo update-index:: Undo update-index::
+ +
@ -96,7 +96,8 @@ $ git-update-index frotz.c filfre.c
$ mailx <2> $ mailx <2>
$ git reset <3> $ git reset <3>
$ git pull git://info.example.com/ nitfol <4> $ git pull git://info.example.com/ nitfol <4>
------------
+
<1> you are happily working on something, and find the changes <1> you are happily working on something, and find the changes
in these files are in good order. You do not want to see them in these files are in good order. You do not want to see them
when you run "git diff", because you plan to work on other files when you run "git diff", because you plan to work on other files
@ -109,7 +110,6 @@ index changes for these two files. Your changes in working tree
remain there. remain there.
<4> then you can pull and merge, leaving frotz.c and filfre.c <4> then you can pull and merge, leaving frotz.c and filfre.c
changes still in the working tree. changes still in the working tree.
------------
Undo a merge or pull:: Undo a merge or pull::
+ +
@ -123,19 +123,18 @@ Auto-merging nitfol
CONFLICT (content): Merge conflict in nitfol CONFLICT (content): Merge conflict in nitfol
Automatic merge failed/prevented; fix up by hand Automatic merge failed/prevented; fix up by hand
$ git reset --hard <2> $ git reset --hard <2>
$ git pull . topic/branch <3>
Updating from 41223... to 13134...
Fast forward
$ git reset --hard ORIG_HEAD <4>
------------
+
<1> try to update from the upstream resulted in a lot of <1> try to update from the upstream resulted in a lot of
conflicts; you were not ready to spend a lot of time merging conflicts; you were not ready to spend a lot of time merging
right now, so you decide to do that later. right now, so you decide to do that later.
<2> "pull" has not made merge commit, so "git reset --hard" <2> "pull" has not made merge commit, so "git reset --hard"
which is a synonym for "git reset --hard HEAD" clears the mess which is a synonym for "git reset --hard HEAD" clears the mess
from the index file and the working tree. from the index file and the working tree.
$ git pull . topic/branch <3>
Updating from 41223... to 13134...
Fast forward
$ git reset --hard ORIG_HEAD <4>
<3> merge a topic branch into the current branch, which resulted <3> merge a topic branch into the current branch, which resulted
in a fast forward. in a fast forward.
<4> but you decided that the topic branch is not ready for public <4> but you decided that the topic branch is not ready for public
@ -143,7 +142,6 @@ consumption yet. "pull" or "merge" always leaves the original
tip of the current branch in ORIG_HEAD, so resetting hard to it tip of the current branch in ORIG_HEAD, so resetting hard to it
brings your index file and the working tree back to that state, 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:: Interrupted workflow::
+ +
@ -162,14 +160,14 @@ $ git commit ;# commit with real log
$ git checkout feature $ git checkout feature
$ git reset --soft HEAD^ ;# go back to WIP state <2> $ git reset --soft HEAD^ ;# go back to WIP state <2>
$ git reset <3> $ git reset <3>
------------
+
<1> This commit will get blown away so a throw-away log message is OK. <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 <2> This removes the 'WIP' commit from the commit history, and sets
your working tree to the state just before you made that snapshot. 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 <3> At this point the index file still has all the WIP changes you
committed in <1>. This sets it to the last commit you were committed as 'snapshot WIP'. This updates the index to show your
basing the WIP changes on. WIP files as uncommitted.
------------
Author Author
------ ------

View File

@ -32,7 +32,7 @@ OPTIONS
-v:: -v::
Be verbose. Be verbose.
--:: \--::
This option can be used to separate command-line options from This option can be used to separate command-line options from
the list of files, (useful when filenames might be mistaken the list of files, (useful when filenames might be mistaken
for command-line options). for command-line options).

View File

@ -13,9 +13,16 @@ SYNOPSIS
DESCRIPTION DESCRIPTION
----------- -----------
Reads a packed archive (.pack) from the standard input, and Read a packed archive (.pack) from the standard input, expanding
expands the objects contained in the pack into "one-file the objects contained within and writing them into the repository in
one-object" format in $GIT_OBJECT_DIRECTORY. "loose" (one object per file) format.
Objects that already exist in the repository will *not* be unpacked
from the pack-file. Therefore, nothing will be unpacked if you use
this command on a pack-file that exists within the target repository.
Please see the `git-repack` documentation for options to generate
new packs and replace existing ones.
OPTIONS OPTIONS
------- -------

View File

@ -11,11 +11,11 @@ SYNOPSIS
[verse] [verse]
'git-update-index' 'git-update-index'
[--add] [--remove | --force-remove] [--replace] [--add] [--remove | --force-remove] [--replace]
[--refresh [-q] [--unmerged] [--ignore-missing]] [--refresh] [-q] [--unmerged] [--ignore-missing]
[--cacheinfo <mode> <object> <file>]\* [--cacheinfo <mode> <object> <file>]\*
[--chmod=(+|-)x] [--chmod=(+|-)x]
[--assume-unchanged | --no-assume-unchanged] [--assume-unchanged | --no-assume-unchanged]
[--really-refresh] [--really-refresh] [--unresolve]
[--info-only] [--index-info] [--info-only] [--index-info]
[-z] [--stdin] [-z] [--stdin]
[--verbose] [--verbose]
@ -80,6 +80,10 @@ OPTIONS
filesystem that has very slow lstat(2) system call filesystem that has very slow lstat(2) system call
(e.g. cifs). (e.g. cifs).
--unresolve::
Restores the 'unmerged' or 'needs updating' state of a
file during a merge if it was cleared by accident.
--info-only:: --info-only::
Do not create objects in the object database for all Do not create objects in the object database for all
<file> arguments that follow this flag; just insert <file> arguments that follow this flag; just insert
@ -109,7 +113,7 @@ OPTIONS
Only meaningful with `--stdin`; paths are separated with Only meaningful with `--stdin`; paths are separated with
NUL character instead of LF. NUL character instead of LF.
--:: \--::
Do not interpret any more arguments as options. Do not interpret any more arguments as options.
<file>:: <file>::
@ -247,8 +251,8 @@ To update and refresh only the files already checked out:
$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh $ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
---------------- ----------------
On an inefficient filesystem with `core.ignorestat` set: On an inefficient filesystem with `core.ignorestat` set::
+
------------ ------------
$ git update-index --really-refresh <1> $ git update-index --really-refresh <1>
$ git update-index --no-assume-unchanged foo.c <2> $ git update-index --no-assume-unchanged foo.c <2>
@ -263,18 +267,17 @@ $ git diff --name-only <7>
$ git update-index --no-assume-unchanged foo.c <8> $ git update-index --no-assume-unchanged foo.c <8>
$ git diff --name-only <9> $ git diff --name-only <9>
M foo.c M foo.c
------------
<1> forces lstat(2) to set "assume unchanged" bits for paths +
that match index. <1> forces lstat(2) to set "assume unchanged" bits for paths that match index.
<2> mark the path to be edited. <2> mark the path to be edited.
<3> this does lstat(2) and finds index matches the path. <3> this does lstat(2) and finds index matches the path.
<4> this does lstat(2) and finds index does not match the path. <4> this does lstat(2) and finds index does *not* match the path.
<5> registering the new version to index sets "assume unchanged" bit. <5> registering the new version to index sets "assume unchanged" bit.
<6> and it is assumed unchanged. <6> and it is assumed unchanged.
<7> even after you edit it. <7> even after you edit it.
<8> you can tell about the change after the fact. <8> you can tell about the change after the fact.
<9> now it checks with lstat(2) and finds it has been changed. <9> now it checks with lstat(2) and finds it has been changed.
------------
Configuration Configuration

View File

@ -17,7 +17,10 @@ Prints a git logical variable.
OPTIONS OPTIONS
------- -------
-l:: -l::
Cause the logical variables to be listed. Cause the logical variables to be listed. In addition, all the
variables of the git configuration file .git/config are listed
as well. (However, the configuration variables listing functionality
is deprecated in favor of `git-repo-config -l`.)
EXAMPLE EXAMPLE
-------- --------
@ -46,6 +49,7 @@ See Also
-------- --------
gitlink:git-commit-tree[1] gitlink:git-commit-tree[1]
gitlink:git-tag[1] gitlink:git-tag[1]
gitlink:git-repo-config[1]
Author Author
------ ------

View File

@ -25,7 +25,7 @@ OPTIONS
-v:: -v::
After verifying the pack, show list of objects contained After verifying the pack, show list of objects contained
in the pack. in the pack.
--:: \--::
Do not interpret any more arguments as options. Do not interpret any more arguments as options.
OUTPUT FORMAT OUTPUT FORMAT

View File

@ -58,7 +58,7 @@ git-whatchanged -p v2.6.12.. include/scsi drivers/scsi::
Show as patches the commits since version 'v2.6.12' that changed Show as patches the commits since version 'v2.6.12' that changed
any file in the include/scsi or drivers/scsi subdirectories any file in the include/scsi or drivers/scsi subdirectories
git-whatchanged --since="2 weeks ago" -- gitk:: git-whatchanged --since="2 weeks ago" \-- gitk::
Show the changes during the last two weeks to the file 'gitk'. Show the changes during the last two weeks to the file 'gitk'.
The "--" is necessary to avoid confusion with the *branch* named The "--" is necessary to avoid confusion with the *branch* named

View File

@ -31,7 +31,7 @@ gitk v2.6.12.. include/scsi drivers/scsi::
Show as the changes since version 'v2.6.12' that changed any Show as the changes since version 'v2.6.12' that changed any
file in the include/scsi or drivers/scsi subdirectories file in the include/scsi or drivers/scsi subdirectories
gitk --since="2 weeks ago" -- gitk:: gitk --since="2 weeks ago" \-- gitk::
Show the changes during the last two weeks to the file 'gitk'. Show the changes during the last two weeks to the file 'gitk'.
The "--" is necessary to avoid confusion with the *branch* named The "--" is necessary to avoid confusion with the *branch* named

View File

@ -1,39 +1,71 @@
object:: alternate object database::
The unit of storage in git. It is uniquely identified by Via the alternates mechanism, a repository can inherit part of its
the SHA1 of its contents. Consequently, an object can not object database from another object database, which is called
be changed. "alternate".
object name:: bare repository::
The unique identifier of an object. The hash of the object's contents A bare repository is normally an appropriately named
using the Secure Hash Algorithm 1 and usually represented by the 40 directory with a `.git` suffix that does not have a
character hexadecimal encoding of the hash of the object (possibly locally checked-out copy of any of the files under revision
followed by a white space). control. That is, all of the `git` administrative and
control files that would normally be present in the
SHA1:: hidden `.git` sub-directory are directly present in
Synonym for object name. the `repository.git` directory instead, and no other files
are present and checked out. Usually publishers of public
object identifier:: repositories make bare repositories available.
Synonym for object name.
hash::
In git's context, synonym to object name.
object database::
Stores a set of "objects", and an individual object is identified
by its object name. The objects usually live in `$GIT_DIR/objects/`.
blob object:: blob object::
Untyped object, e.g. the contents of a file. Untyped object, e.g. the contents of a file.
tree object:: branch::
An object containing a list of file names and modes along with refs A non-cyclical graph of revisions, i.e. the complete history of
to the associated blob and/or tree objects. A tree is equivalent a particular revision, which is called the branch head. The
to a directory. branch heads are stored in `$GIT_DIR/refs/heads/`.
tree:: cache::
Either a working tree, or a tree object together with the Obsolete for: index.
dependent blob and tree objects (i.e. a stored representation
of a working tree). chain::
A list of objects, where each object in the list contains a
reference to its successor (for example, the successor of a commit
could be one of its parents).
changeset::
BitKeeper/cvsps speak for "commit". Since git does not store
changes, but states, it really does not make sense to use
the term "changesets" with git.
checkout::
The action of updating the working tree to a revision which was
stored in the object database.
cherry-picking::
In SCM jargon, "cherry pick" means to choose a subset of
changes out of a series of changes (typically commits)
and record them as a new series of changes on top of
different codebase. In GIT, this is performed by
"git cherry-pick" command to extract the change
introduced by an existing commit and to record it based
on the tip of the current branch as a new commit.
clean::
A working tree is clean, if it corresponds to the revision
referenced by the current head. Also see "dirty".
commit::
As a verb: The action of storing the current state of the index in the
object database. The result is a revision.
As a noun: Short hand for commit object.
commit object::
An object which contains the information about a particular
revision, such as parents, committer, author, date and the
tree object which corresponds to the top directory of the
stored revision.
core git::
Fundamental data structures and utilities of git. Exposes only
limited source code management tools.
DAG:: DAG::
Directed acyclic graph. The commit objects form a directed acyclic Directed acyclic graph. The commit objects form a directed acyclic
@ -41,6 +73,63 @@ DAG::
objects is acyclic (there is no chain which begins and ends with the objects is acyclic (there is no chain which begins and ends with the
same object). same object).
dircache::
You are *waaaaay* behind.
dirty::
A working tree is said to be dirty if it contains modifications
which have not been committed to the current branch.
directory::
The list you get with "ls" :-)
ent::
Favorite synonym to "tree-ish" by some total geeks. See
`http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth
explanation.
fast forward::
A fast-forward is a special type of merge where you have
a revision and you are "merging" another branch's changes
that happen to be a descendant of what you have.
In such these cases, you do not make a new merge commit but
instead just update to his revision. This will happen
frequently on a tracking branch of a remote repository.
fetch::
Fetching a branch means to get the branch's head ref from a
remote repository, to find out which objects are missing from
the local object database, and to get them, too.
file system::
Linus Torvalds originally designed git to be a user space file
system, i.e. the infrastructure to hold files and directories.
That ensured the efficiency and speed of git.
git archive::
Synonym for repository (for arch people).
hash::
In git's context, synonym to object name.
head::
The top of a branch. It contains a ref to the corresponding
commit object.
head ref::
A ref pointing to a head. Often, this is abbreviated to "head".
Head refs are stored in `$GIT_DIR/refs/heads/`.
hook::
During the normal execution of several git commands,
call-outs are made to optional scripts that allow
a developer to add functionality or checking.
Typically, the hooks allow for a command to be pre-verified
and potentially aborted, and allow for a post-notification
after the operation is done.
The hook scripts are found in the `$GIT_DIR/hooks/` directory,
and are enabled by simply making them executable.
index:: index::
A collection of files with stat information, whose contents are A collection of files with stat information, whose contents are
stored as objects. The index is a stored version of your working stored as objects. The index is a stored version of your working
@ -53,92 +142,167 @@ index entry::
yet finished (i.e. if the index contains multiple versions of yet finished (i.e. if the index contains multiple versions of
that file). that file).
unmerged index: master::
An index which contains unmerged index entries. The default development 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, though that is purely conventional and not required.
cache:: merge::
Obsolete for: index. To merge branches means to try to accumulate the changes since a
common ancestor and apply them to the first branch. An automatic
merge uses heuristics to accomplish that. Evidently, an automatic
merge can fail.
working tree:: object::
The set of files and directories currently being worked on, The unit of storage in git. It is uniquely identified by
i.e. you can work in your working tree without using git at all. the SHA1 of its contents. Consequently, an object can not
be changed.
directory:: object database::
The list you get with "ls" :-) Stores a set of "objects", and an individual object is identified
by its object name. The objects usually live in `$GIT_DIR/objects/`.
revision:: object identifier::
A particular state of files and directories which was stored in Synonym for object name.
the object database. It is referenced by a commit object.
checkout:: object name::
The action of updating the working tree to a revision which was The unique identifier of an object. The hash of the object's contents
stored in the object database. using the Secure Hash Algorithm 1 and usually represented by the 40
character hexadecimal encoding of the hash of the object (possibly
followed by a white space).
commit:: object type:
As a verb: The action of storing the current state of the index in the One of the identifiers "commit","tree","tag" and "blob" describing
object database. The result is a revision. the type of an object.
As a noun: Short hand for commit object.
commit object:: octopus::
An object which contains the information about a particular To merge more than two branches. Also denotes an intelligent
revision, such as parents, committer, author, date and the predator.
tree object which corresponds to the top directory of the
stored revision. origin::
The default upstream tracking branch. Most projects have at
least one upstream project which they track. By default
'origin' is used for that purpose. New upstream updates
will be fetched into this branch; you should never commit
to it yourself.
pack::
A set of objects which have been compressed into one file (to save
space or to transmit them efficiently).
pack index::
The list of identifiers, and other information, of the objects in a
pack, to assist in efficiently accessing the contents of a pack.
parent:: parent::
A commit object contains a (possibly empty) list of the logical A commit object contains a (possibly empty) list of the logical
predecessor(s) in the line of development, i.e. its parents. predecessor(s) in the line of development, i.e. its parents.
changeset:: pickaxe::
BitKeeper/cvsps speak for "commit". Since git does not store The term pickaxe refers to an option to the diffcore routines
changes, but states, it really does not make sense to use that help select changes that add or delete a given text string.
the term "changesets" with git. With the --pickaxe-all option, it can be used to view the
full changeset that introduced or removed, say, a particular
line of text. See gitlink:git-diff[1].
clean:: plumbing::
A working tree is clean, if it corresponds to the revision Cute name for core git.
referenced by the current head.
dirty:: porcelain::
A working tree is said to be dirty if it contains modifications Cute name for programs and program suites depending on core git,
which have not been committed to the current branch. presenting a high level access to core git. Porcelains expose
more of a SCM interface than the plumbing.
head:: pull::
The top of a branch. It contains a ref to the corresponding Pulling a branch means to fetch it and merge it.
commit object.
branch:: push::
A non-cyclical graph of revisions, i.e. the complete history of Pushing a branch means to get the branch's head ref from a remote
a particular revision, which is called the branch head. The repository, find out if it is an ancestor to the branch's local
branch heads are stored in `$GIT_DIR/refs/heads/`. head ref is a direct, and in that case, putting all objects, which
are reachable from the local head ref, and which are missing from
the remote repository, into the remote object database, and updating
the remote head ref. If the remote head is not an ancestor to the
local head, the push fails.
master:: reachable::
The default branch. Whenever you create a git repository, a branch An object is reachable from a ref/commit/tree/tag, if there is a
named "master" is created, and becomes the active branch. In most chain leading from the latter to the former.
cases, this contains the local development.
origin:: rebase::
The default upstream branch. Most projects have one upstream To clean a branch by starting from the head of the main line of
project which they track, and by default 'origin' is used for development ("master"), and reapply the (possibly cherry-picked)
that purpose. New updates from upstream will be fetched into changes from that branch.
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 or a name that denotes
object. These may be stored in `$GIT_DIR/refs/`. a particular object. These may be stored in `$GIT_DIR/refs/`.
head ref:: refspec::
A ref pointing to a head. Often, this is abbreviated to "head". A refspec is used by fetch and push to describe the mapping
Head refs are stored in `$GIT_DIR/refs/heads/`. between remote ref and local ref. They are combined with
a colon in the format <src>:<dst>, preceded by an optional
plus sign, +. For example:
`git fetch $URL refs/heads/master:refs/heads/origin`
means "grab the master branch head from the $URL and store
it as my origin branch head".
And `git push $URL refs/heads/master:refs/heads/to-upstream`
means "publish my master branch head as to-upstream master head
at $URL". See also gitlink:git-push[1]
repository::
A collection of refs together with an object database containing
all objects, which are reachable from the refs, possibly accompanied
by meta data from one or more porcelains. A repository can
share an object database with other repositories.
resolve::
The action of fixing up manually what a failed automatic merge
left behind.
revision::
A particular state of files and directories which was stored in
the object database. It is referenced by a commit object.
rewind::
To throw away part of the development, i.e. to assign the head to
an earlier revision.
SCM::
Source code management (tool).
SHA1::
Synonym for object name.
topic branch::
A regular git branch that is used by a developer to
identify a conceptual line of development. Since branches
are very easy and inexpensive, it is often desirable to
have several small branches that each contain very well
defined concepts or small incremental yet related changes.
tracking branch::
A regular git branch that is used to follow changes from
another repository. A tracking branch should not contain
direct modifications or have local commits made to it.
A tracking branch can usually be identified as the
right-hand-side ref in a Pull: refspec.
tree object::
An object containing a list of file names and modes along with refs
to the associated blob and/or tree objects. A tree is equivalent
to a directory.
tree::
Either a working tree, or a tree object together with the
dependent blob and tree objects (i.e. a stored representation
of a working tree).
tree-ish:: tree-ish::
A ref pointing to either a commit object, a tree object, or a A ref pointing to either a commit object, a tree object, or a
tag object pointing to a tag or commit or tree object. tag object pointing to a tag or commit or tree object.
ent::
Favorite synonym to "tree-ish" by some total geeks. See
`http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth
explanation.
tag object:: tag object::
An object containing a ref pointing to another object, which can An object containing a ref pointing to another object, which can
contain a message just like a commit object. It can also contain a message just like a commit object. It can also
@ -153,101 +317,10 @@ tag::
A tag is most typically used to mark a particular point in the A tag is most typically used to mark a particular point in the
commit ancestry chain. commit ancestry chain.
merge:: unmerged index:
To merge branches means to try to accumulate the changes since a An index which contains unmerged index entries.
common ancestor and apply them to the first branch. An automatic
merge uses heuristics to accomplish that. Evidently, an automatic
merge can fail.
octopus:: working tree::
To merge more than two branches. Also denotes an intelligent The set of files and directories currently being worked on,
predator. i.e. you can work in your working tree without using git at all.
resolve::
The action of fixing up manually what a failed automatic merge
left behind.
rewind::
To throw away part of the development, i.e. to assign the head to
an earlier revision.
rebase::
To clean a branch by starting from the head of the main line of
development ("master"), and reapply the (possibly cherry-picked)
changes from that branch.
repository::
A collection of refs together with an object database containing
all objects, which are reachable from the refs, possibly accompanied
by meta data from one or more porcelains. A repository can
share an object database with other repositories.
git archive::
Synonym for repository (for arch people).
file system::
Linus Torvalds originally designed git to be a user space file
system, i.e. the infrastructure to hold files and directories.
That ensured the efficiency and speed of git.
alternate object database::
Via the alternates mechanism, a repository can inherit part of its
object database from another object database, which is called
"alternate".
reachable::
An object is reachable from a ref/commit/tree/tag, if there is a
chain leading from the latter to the former.
chain::
A list of objects, where each object in the list contains a
reference to its successor (for example, the successor of a commit
could be one of its parents).
fetch::
Fetching a branch means to get the branch's head ref from a
remote repository, to find out which objects are missing from
the local object database, and to get them, too.
pull::
Pulling a branch means to fetch it and merge it.
push::
Pushing a branch means to get the branch's head ref from a remote
repository, find out if it is an ancestor to the branch's local
head ref is a direct, and in that case, putting all objects, which
are reachable from the local head ref, and which are missing from
the remote repository, into the remote object database, and updating
the remote head ref. If the remote head is not an ancestor to the
local head, the push fails.
pack::
A set of objects which have been compressed into one file (to save
space or to transmit them efficiently).
pack index::
The list of identifiers, and other information, of the objects in a
pack, to assist in efficiently accessing the contents of a pack.
core git::
Fundamental data structures and utilities of git. Exposes only
limited source code management tools.
plumbing::
Cute name for core git.
porcelain::
Cute name for programs and program suites depending on core git,
presenting a high level access to core git. Porcelains expose
more of a SCM interface than the plumbing.
object type:
One of the identifiers "commit","tree","tag" and "blob" describing
the type of an object.
SCM::
Source code management (tool).
dircache::
You are *waaaaay* behind.

View File

@ -48,7 +48,7 @@ This list is sorted alphabetically:
'; ';
@keys=sort {uc($a) cmp uc($b)} keys %terms; @keys=sort {uc($a) cmp uc($b)} keys %terms;
$pattern='(\b'.join('\b|\b',reverse @keys).'\b)'; $pattern='(\b(?<!link:git-)'.join('\b|\b(?<!link:git-)',reverse @keys).'\b)';
foreach $key (@keys) { foreach $key (@keys) {
$terms{$key}=~s/$pattern/sprintf "<<ref_".no_spaces($1).",$1>>";/eg; $terms{$key}=~s/$pattern/sprintf "<<ref_".no_spaces($1).",$1>>";/eg;
print '[[ref_'.no_spaces($key).']]'.$key."::\n" print '[[ref_'.no_spaces($key).']]'.$key."::\n"

View File

@ -28,8 +28,8 @@ all:
# #
# 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. # Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
# Don't enable it on Windows. # Enable it on Windows. By default, symrefs are still used.
# #
# 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.
@ -115,13 +115,13 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
SCRIPT_SH = \ SCRIPT_SH = \
git-add.sh git-bisect.sh git-branch.sh git-checkout.sh \ git-add.sh git-bisect.sh git-branch.sh git-checkout.sh \
git-cherry.sh git-clean.sh git-clone.sh git-commit.sh \ git-cherry.sh git-clean.sh git-clone.sh git-commit.sh \
git-count-objects.sh git-diff.sh git-fetch.sh \ git-fetch.sh \
git-format-patch.sh git-ls-remote.sh \ git-format-patch.sh git-ls-remote.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-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-rm.sh git-sh-setup.sh \ git-resolve.sh git-revert.sh git-rm.sh git-sh-setup.sh \
git-tag.sh git-verify-tag.sh git-whatchanged.sh \ git-tag.sh git-verify-tag.sh \
git-applymbox.sh git-applypatch.sh git-am.sh \ git-applymbox.sh git-applypatch.sh git-am.sh \
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \ git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
git-merge-resolve.sh git-merge-ours.sh git-grep.sh \ git-merge-resolve.sh git-merge-ours.sh git-grep.sh \
@ -139,7 +139,7 @@ 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)) \
git-cherry-pick git-show git-status git-cherry-pick git-status
# The ones that do not have to link with lcrypto, lz nor xdiff. # The ones that do not have to link with lcrypto, lz nor xdiff.
SIMPLE_PROGRAMS = \ SIMPLE_PROGRAMS = \
@ -167,7 +167,8 @@ PROGRAMS = \
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 git-merge-tree$X git-blame$X git-imap-send$X git-describe$X git-merge-tree$X git-blame$X git-imap-send$X
BUILT_INS = git-log$X BUILT_INS = git-log$X git-whatchanged$X git-show$X \
git-count-objects$X git-diff$X git-push$X
# what 'all' will build and 'install' will install, in gitexecdir # what 'all' will build and 'install' will install, in gitexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS) ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
@ -199,7 +200,7 @@ LIB_H = \
tree-walk.h log-tree.h tree-walk.h log-tree.h
DIFF_OBJS = \ DIFF_OBJS = \
diff-lib.o diffcore-break.o diffcore-order.o \ diff.o diff-lib.o diffcore-break.o diffcore-order.o \
diffcore-pickaxe.o diffcore-rename.o tree-diff.o combine-diff.o \ diffcore-pickaxe.o diffcore-rename.o tree-diff.o combine-diff.o \
diffcore-delta.o log-tree.o diffcore-delta.o log-tree.o
@ -214,7 +215,7 @@ LIB_OBJS = \
$(DIFF_OBJS) $(DIFF_OBJS)
BUILTIN_OBJS = \ BUILTIN_OBJS = \
builtin-log.o builtin-help.o builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o
GITLIBS = $(LIB_FILE) $(XDIFF_LIB) GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
LIBS = $(GITLIBS) -lz LIBS = $(GITLIBS) -lz
@ -263,6 +264,7 @@ ifeq ($(uname_O),Cygwin)
NO_D_TYPE_IN_DIRENT = YesPlease NO_D_TYPE_IN_DIRENT = YesPlease
NO_D_INO_IN_DIRENT = YesPlease NO_D_INO_IN_DIRENT = YesPlease
NO_STRCASESTR = YesPlease NO_STRCASESTR = YesPlease
NO_SYMLINK_HEAD = YesPlease
NEEDS_LIBICONV = YesPlease NEEDS_LIBICONV = YesPlease
# There are conflicting reports about this. # There are conflicting reports about this.
# On some boxes NO_MMAP is needed, and not so elsewhere. # On some boxes NO_MMAP is needed, and not so elsewhere.
@ -386,6 +388,9 @@ endif
ifdef NO_D_INO_IN_DIRENT ifdef NO_D_INO_IN_DIRENT
ALL_CFLAGS += -DNO_D_INO_IN_DIRENT ALL_CFLAGS += -DNO_D_INO_IN_DIRENT
endif endif
ifdef NO_SYMLINK_HEAD
ALL_CFLAGS += -DNO_SYMLINK_HEAD
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
@ -470,6 +475,8 @@ git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS)
$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \ $(ALL_CFLAGS) -o $@ $(filter %.c,$^) \
$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
builtin-help.o: common-cmds.h
$(BUILT_INS): git$X $(BUILT_INS): git$X
rm -f $@ && ln git$X $@ rm -f $@ && ln git$X $@
@ -503,9 +510,6 @@ $(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 git-status: git-commit
cp $< $@ cp $< $@
@ -560,10 +564,6 @@ git-http-push$X: revision.o http.o http-push.o $(LIB_FILE)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
git-rev-list$X: rev-list.o $(LIB_FILE)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(OPENSSL_LIBSSL)
init-db.o: init-db.c init-db.o: init-db.c
$(CC) -c $(ALL_CFLAGS) \ $(CC) -c $(ALL_CFLAGS) \
-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c
@ -573,12 +573,12 @@ $(patsubst git-%$X,%.o,$(PROGRAMS)): $(GITLIBS)
$(DIFF_OBJS): diffcore.h $(DIFF_OBJS): diffcore.h
$(LIB_FILE): $(LIB_OBJS) $(LIB_FILE): $(LIB_OBJS)
$(AR) rcs $@ $(LIB_OBJS) rm -f $@ && $(AR) rcs $@ $(LIB_OBJS)
XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o
$(XDIFF_LIB): $(XDIFF_OBJS) $(XDIFF_LIB): $(XDIFF_OBJS)
$(AR) rcs $@ $(XDIFF_OBJS) rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS)
doc: doc:

10
blame.c
View File

@ -515,9 +515,9 @@ static int compare_tree_path(struct rev_info* revs,
paths[1] = NULL; paths[1] = NULL;
diff_tree_setup_paths(get_pathspec(revs->prefix, paths), diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
&revs->diffopt); &revs->pruning);
ret = rev_compare_tree(revs, c1->tree, c2->tree); ret = rev_compare_tree(revs, c1->tree, c2->tree);
diff_tree_release_paths(&revs->diffopt); diff_tree_release_paths(&revs->pruning);
return ret; return ret;
} }
@ -531,9 +531,9 @@ static int same_tree_as_empty_path(struct rev_info *revs, struct tree* t1,
paths[1] = NULL; paths[1] = NULL;
diff_tree_setup_paths(get_pathspec(revs->prefix, paths), diff_tree_setup_paths(get_pathspec(revs->prefix, paths),
&revs->diffopt); &revs->pruning);
ret = rev_same_tree_as_empty(revs, t1); ret = rev_same_tree_as_empty(revs, t1);
diff_tree_release_paths(&revs->diffopt); diff_tree_release_paths(&revs->pruning);
return ret; return ret;
} }
@ -834,7 +834,7 @@ int main(int argc, const char **argv)
args[0] = filename; args[0] = filename;
args[1] = NULL; args[1] = NULL;
diff_tree_setup_paths(args, &rev.diffopt); diff_tree_setup_paths(args, &rev.pruning);
prepare_revision_walk(&rev); prepare_revision_walk(&rev);
process_commits(&rev, filename, &initial); process_commits(&rev, filename, &initial);

125
builtin-count.c Normal file
View File

@ -0,0 +1,125 @@
/*
* Builtin "git count-objects".
*
* Copyright (c) 2006 Junio C Hamano
*/
#include "cache.h"
#include "builtin.h"
static const char count_objects_usage[] = "git-count-objects [-v]";
static void count_objects(DIR *d, char *path, int len, int verbose,
unsigned long *loose,
unsigned long *loose_size,
unsigned long *packed_loose,
unsigned long *garbage)
{
struct dirent *ent;
while ((ent = readdir(d)) != NULL) {
char hex[41];
unsigned char sha1[20];
const char *cp;
int bad = 0;
if ((ent->d_name[0] == '.') &&
(ent->d_name[1] == 0 ||
((ent->d_name[1] == '.') && (ent->d_name[2] == 0))))
continue;
for (cp = ent->d_name; *cp; cp++) {
int ch = *cp;
if (('0' <= ch && ch <= '9') ||
('a' <= ch && ch <= 'f'))
continue;
bad = 1;
break;
}
if (cp - ent->d_name != 38)
bad = 1;
else {
struct stat st;
memcpy(path + len + 3, ent->d_name, 38);
path[len + 2] = '/';
path[len + 41] = 0;
if (lstat(path, &st) || !S_ISREG(st.st_mode))
bad = 1;
else
(*loose_size) += st.st_blocks;
}
if (bad) {
if (verbose) {
error("garbage found: %.*s/%s",
len + 2, path, ent->d_name);
(*garbage)++;
}
continue;
}
(*loose)++;
if (!verbose)
continue;
memcpy(hex, path+len, 2);
memcpy(hex+2, ent->d_name, 38);
hex[40] = 0;
if (get_sha1_hex(hex, sha1))
die("internal error");
if (has_sha1_pack(sha1))
(*packed_loose)++;
}
}
int cmd_count_objects(int ac, const char **av, char **ep)
{
int i;
int verbose = 0;
const char *objdir = get_object_directory();
int len = strlen(objdir);
char *path = xmalloc(len + 50);
unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
unsigned long loose_size = 0;
for (i = 1; i < ac; i++) {
const char *arg = av[i];
if (*arg != '-')
break;
else if (!strcmp(arg, "-v"))
verbose = 1;
else
usage(count_objects_usage);
}
/* we do not take arguments other than flags for now */
if (i < ac)
usage(count_objects_usage);
memcpy(path, objdir, len);
if (len && objdir[len-1] != '/')
path[len++] = '/';
for (i = 0; i < 256; i++) {
DIR *d;
sprintf(path + len, "%02x", i);
d = opendir(path);
if (!d)
continue;
count_objects(d, path, len, verbose,
&loose, &loose_size, &packed_loose, &garbage);
closedir(d);
}
if (verbose) {
struct packed_git *p;
if (!packed_git)
prepare_packed_git();
for (p = packed_git; p; p = p->next) {
if (!p->pack_local)
continue;
packed += num_packed_objects(p);
}
printf("count: %lu\n", loose);
printf("size: %lu\n", loose_size / 2);
printf("in-pack: %lu\n", packed);
printf("prune-packable: %lu\n", packed_loose);
printf("garbage: %lu\n", garbage);
}
else
printf("%lu objects, %lu kilobytes\n",
loose, loose_size / 2);
return 0;
}

369
builtin-diff.c Normal file
View File

@ -0,0 +1,369 @@
/*
* Builtin "git diff"
*
* Copyright (c) 2006 Junio C Hamano
*/
#include "cache.h"
#include "commit.h"
#include "blob.h"
#include "tag.h"
#include "diff.h"
#include "diffcore.h"
#include "revision.h"
#include "log-tree.h"
#include "builtin.h"
/* NEEDSWORK: struct object has place for name but we _do_
* know mode when we extracted the blob out of a tree, which
* we currently lose.
*/
struct blobinfo {
unsigned char sha1[20];
const char *name;
};
static const char builtin_diff_usage[] =
"diff <options> <rev>{0,2} -- <path>*";
static int builtin_diff_files(struct rev_info *revs,
int argc, const char **argv)
{
int silent = 0;
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--base"))
revs->max_count = 1;
else if (!strcmp(arg, "--ours"))
revs->max_count = 2;
else if (!strcmp(arg, "--theirs"))
revs->max_count = 3;
else if (!strcmp(arg, "-q"))
silent = 1;
else if (!strcmp(arg, "--raw"))
revs->diffopt.output_format = DIFF_FORMAT_RAW;
else
usage(builtin_diff_usage);
argv++; argc--;
}
/*
* Make sure there are NO revision (i.e. pending object) parameter,
* specified rev.max_count is reasonable (0 <= n <= 3), and
* there is no other revision filtering parameter.
*/
if (revs->pending_objects ||
revs->min_age != -1 ||
revs->max_age != -1 ||
3 < revs->max_count)
usage(builtin_diff_usage);
if (revs->max_count < 0 &&
(revs->diffopt.output_format == DIFF_FORMAT_PATCH))
revs->combine_merges = revs->dense_combined_merges = 1;
/*
* Backward compatibility wart - "diff-files -s" used to
* defeat the common diff option "-s" which asked for
* DIFF_FORMAT_NO_OUTPUT.
*/
if (revs->diffopt.output_format == DIFF_FORMAT_NO_OUTPUT)
revs->diffopt.output_format = DIFF_FORMAT_RAW;
return run_diff_files(revs, silent);
}
static void stuff_change(struct diff_options *opt,
unsigned old_mode, unsigned new_mode,
const unsigned char *old_sha1,
const unsigned char *new_sha1,
const char *old_name,
const char *new_name)
{
struct diff_filespec *one, *two;
if (memcmp(null_sha1, old_sha1, 20) &&
memcmp(null_sha1, new_sha1, 20) &&
!memcmp(old_sha1, new_sha1, 20))
return;
if (opt->reverse_diff) {
unsigned tmp;
const
const unsigned char *tmp_u;
const char *tmp_c;
tmp = old_mode; old_mode = new_mode; new_mode = tmp;
tmp_u = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_u;
tmp_c = old_name; old_name = new_name; new_name = tmp_c;
}
one = alloc_filespec(old_name);
two = alloc_filespec(new_name);
fill_filespec(one, old_sha1, old_mode);
fill_filespec(two, new_sha1, new_mode);
/* NEEDSWORK: shouldn't this part of diffopt??? */
diff_queue(&diff_queued_diff, one, two);
}
static int builtin_diff_b_f(struct rev_info *revs,
int argc, const char **argv,
struct blobinfo *blob,
const char *path)
{
/* Blob vs file in the working tree*/
struct stat st;
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--raw"))
revs->diffopt.output_format = DIFF_FORMAT_RAW;
else
usage(builtin_diff_usage);
argv++; argc--;
}
if (lstat(path, &st))
die("'%s': %s", path, strerror(errno));
if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)))
die("'%s': not a regular file or symlink", path);
stuff_change(&revs->diffopt,
canon_mode(st.st_mode), canon_mode(st.st_mode),
blob[0].sha1, null_sha1,
blob[0].name, path);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
return 0;
}
static int builtin_diff_blobs(struct rev_info *revs,
int argc, const char **argv,
struct blobinfo *blob)
{
/* Blobs */
unsigned mode = canon_mode(S_IFREG | 0644);
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--raw"))
revs->diffopt.output_format = DIFF_FORMAT_RAW;
else
usage(builtin_diff_usage);
argv++; argc--;
}
stuff_change(&revs->diffopt,
mode, mode,
blob[0].sha1, blob[1].sha1,
blob[1].name, blob[1].name);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
return 0;
}
static int builtin_diff_index(struct rev_info *revs,
int argc, const char **argv)
{
int cached = 0;
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--cached"))
cached = 1;
else if (!strcmp(arg, "--raw"))
revs->diffopt.output_format = DIFF_FORMAT_RAW;
else
usage(builtin_diff_usage);
argv++; argc--;
}
/*
* Make sure there is one revision (i.e. pending object),
* and there is no revision filtering parameters.
*/
if (!revs->pending_objects || revs->pending_objects->next ||
revs->max_count != -1 || revs->min_age != -1 ||
revs->max_age != -1)
usage(builtin_diff_usage);
return run_diff_index(revs, cached);
}
static int builtin_diff_tree(struct rev_info *revs,
int argc, const char **argv,
struct object_list *ent)
{
const unsigned char *(sha1[2]);
int swap = 1;
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--raw"))
revs->diffopt.output_format = DIFF_FORMAT_RAW;
else
usage(builtin_diff_usage);
argv++; argc--;
}
/* We saw two trees, ent[0] and ent[1].
* unless ent[0] is unintesting, they are swapped
*/
if (ent[0].item->flags & UNINTERESTING)
swap = 0;
sha1[swap] = ent[0].item->sha1;
sha1[1-swap] = ent[1].item->sha1;
diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt);
log_tree_diff_flush(revs);
return 0;
}
static int builtin_diff_combined(struct rev_info *revs,
int argc, const char **argv,
struct object_list *ent,
int ents)
{
const unsigned char (*parent)[20];
int i;
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--raw"))
revs->diffopt.output_format = DIFF_FORMAT_RAW;
else
usage(builtin_diff_usage);
argv++; argc--;
}
if (!revs->dense_combined_merges && !revs->combine_merges)
revs->dense_combined_merges = revs->combine_merges = 1;
parent = xmalloc(ents * sizeof(*parent));
/* Again, the revs are all reverse */
for (i = 0; i < ents; i++)
memcpy(parent + i, ent[ents - 1 - i].item->sha1, 20);
diff_tree_combined(parent[0], parent + 1, ents - 1,
revs->dense_combined_merges, revs);
return 0;
}
static void add_head(struct rev_info *revs)
{
unsigned char sha1[20];
struct object *obj;
if (get_sha1("HEAD", sha1))
return;
obj = parse_object(sha1);
if (!obj)
return;
add_object(obj, &revs->pending_objects, NULL, "HEAD");
}
int cmd_diff(int argc, const char **argv, char **envp)
{
struct rev_info rev;
struct object_list *list, ent[100];
int ents = 0, blobs = 0, paths = 0;
const char *path = NULL;
struct blobinfo blob[2];
/*
* We could get N tree-ish in the rev.pending_objects list.
* Also there could be M blobs there, and P pathspecs.
*
* N=0, M=0:
* cache vs files (diff-files)
* N=0, M=2:
* compare two random blobs. P must be zero.
* N=0, M=1, P=1:
* compare a blob with a working tree file.
*
* N=1, M=0:
* tree vs cache (diff-index --cached)
*
* N=2, M=0:
* tree vs tree (diff-tree)
*
* Other cases are errors.
*/
git_config(git_diff_config);
init_revisions(&rev);
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
argc = setup_revisions(argc, argv, &rev, NULL);
/* Do we have --cached and not have a pending object, then
* default to HEAD by hand. Eek.
*/
if (!rev.pending_objects) {
int i;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--"))
break;
else if (!strcmp(arg, "--cached")) {
add_head(&rev);
break;
}
}
}
for (list = rev.pending_objects; list; list = list->next) {
struct object *obj = list->item;
const char *name = list->name;
int flags = (obj->flags & UNINTERESTING);
if (!obj->parsed)
obj = parse_object(obj->sha1);
obj = deref_tag(obj, NULL, 0);
if (!obj)
die("invalid object '%s' given.", name);
if (!strcmp(obj->type, commit_type))
obj = &((struct commit *)obj)->tree->object;
if (!strcmp(obj->type, tree_type)) {
if (ARRAY_SIZE(ent) <= ents)
die("more than %d trees given: '%s'",
(int) ARRAY_SIZE(ent), name);
obj->flags |= flags;
ent[ents].item = obj;
ent[ents].name = name;
ents++;
continue;
}
if (!strcmp(obj->type, blob_type)) {
if (2 <= blobs)
die("more than two blobs given: '%s'", name);
memcpy(blob[blobs].sha1, obj->sha1, 20);
blob[blobs].name = name;
blobs++;
continue;
}
die("unhandled object '%s' given.", name);
}
if (rev.prune_data) {
const char **pathspec = rev.prune_data;
while (*pathspec) {
if (!path)
path = *pathspec;
paths++;
pathspec++;
}
}
/*
* Now, do the arguments look reasonable?
*/
if (!ents) {
switch (blobs) {
case 0:
return builtin_diff_files(&rev, argc, argv);
break;
case 1:
if (paths != 1)
usage(builtin_diff_usage);
return builtin_diff_b_f(&rev, argc, argv, blob, path);
break;
case 2:
if (paths)
usage(builtin_diff_usage);
return builtin_diff_blobs(&rev, argc, argv, blob);
break;
default:
usage(builtin_diff_usage);
}
}
else if (blobs)
usage(builtin_diff_usage);
else if (ents == 1)
return builtin_diff_index(&rev, argc, argv);
else if (ents == 2)
return builtin_diff_tree(&rev, argc, argv, ent);
else
return builtin_diff_combined(&rev, argc, argv, ent, ents);
usage(builtin_diff_usage);
}

View File

@ -3,6 +3,7 @@
* *
* Builtin help-related commands (help, usage, version) * Builtin help-related commands (help, usage, version)
*/ */
#include <sys/ioctl.h>
#include "cache.h" #include "cache.h"
#include "builtin.h" #include "builtin.h"
#include "exec_cmd.h" #include "exec_cmd.h"

312
builtin-push.c Normal file
View File

@ -0,0 +1,312 @@
/*
* "git push"
*/
#include "cache.h"
#include "refs.h"
#include "run-command.h"
#include "builtin.h"
#define MAX_URI (16)
static const char push_usage[] = "git push [--all] [--tags] [--force] <repository> [<refspec>...]";
static int all = 0, tags = 0, force = 0, thin = 1;
static const char *execute = NULL;
#define BUF_SIZE (2084)
static char buffer[BUF_SIZE];
static const char **refspec = NULL;
static int refspec_nr = 0;
static void add_refspec(const char *ref)
{
int nr = refspec_nr + 1;
refspec = xrealloc(refspec, nr * sizeof(char *));
refspec[nr-1] = ref;
refspec_nr = nr;
}
static int expand_one_ref(const char *ref, const unsigned char *sha1)
{
/* Ignore the "refs/" at the beginning of the refname */
ref += 5;
if (strncmp(ref, "tags/", 5))
return 0;
add_refspec(strdup(ref));
return 0;
}
static void expand_refspecs(void)
{
if (all) {
if (refspec_nr)
die("cannot mix '--all' and a refspec");
/*
* No need to expand "--all" - we'll just use
* the "--all" flag to send-pack
*/
return;
}
if (!tags)
return;
for_each_ref(expand_one_ref);
}
static void set_refspecs(const char **refs, int nr)
{
if (nr) {
size_t bytes = nr * sizeof(char *);
refspec = xrealloc(refspec, bytes);
memcpy(refspec, refs, bytes);
refspec_nr = nr;
}
expand_refspecs();
}
static int get_remotes_uri(const char *repo, const char *uri[MAX_URI])
{
int n = 0;
FILE *f = fopen(git_path("remotes/%s", repo), "r");
int has_explicit_refspec = refspec_nr || all || tags;
if (!f)
return -1;
while (fgets(buffer, BUF_SIZE, f)) {
int is_refspec;
char *s, *p;
if (!strncmp("URL: ", buffer, 5)) {
is_refspec = 0;
s = buffer + 5;
} else if (!strncmp("Push: ", buffer, 6)) {
is_refspec = 1;
s = buffer + 6;
} else
continue;
/* Remove whitespace at the head.. */
while (isspace(*s))
s++;
if (!*s)
continue;
/* ..and at the end */
p = s + strlen(s);
while (isspace(p[-1]))
*--p = 0;
if (!is_refspec) {
if (n < MAX_URI)
uri[n++] = strdup(s);
else
error("more than %d URL's specified, ignoreing the rest", MAX_URI);
}
else if (is_refspec && !has_explicit_refspec)
add_refspec(strdup(s));
}
fclose(f);
if (!n)
die("remote '%s' has no URL", repo);
return n;
}
static const char **config_uri;
static const char *config_repo;
static int config_repo_len;
static int config_current_uri;
static int config_get_refspecs;
static int get_remote_config(const char* key, const char* value)
{
if (!strncmp(key, "remote.", 7) &&
!strncmp(key + 7, config_repo, config_repo_len)) {
if (!strcmp(key + 7 + config_repo_len, ".url")) {
if (config_current_uri < MAX_URI)
config_uri[config_current_uri++] = strdup(value);
else
error("more than %d URL's specified, ignoring the rest", MAX_URI);
}
else if (config_get_refspecs &&
!strcmp(key + 7 + config_repo_len, ".push"))
add_refspec(strdup(value));
}
return 0;
}
static int get_config_remotes_uri(const char *repo, const char *uri[MAX_URI])
{
config_repo_len = strlen(repo);
config_repo = repo;
config_current_uri = 0;
config_uri = uri;
config_get_refspecs = !(refspec_nr || all || tags);
git_config(get_remote_config);
return config_current_uri;
}
static int get_branches_uri(const char *repo, const char *uri[MAX_URI])
{
const char *slash = strchr(repo, '/');
int n = slash ? slash - repo : 1000;
FILE *f = fopen(git_path("branches/%.*s", n, repo), "r");
char *s, *p;
int len;
if (!f)
return 0;
s = fgets(buffer, BUF_SIZE, f);
fclose(f);
if (!s)
return 0;
while (isspace(*s))
s++;
if (!*s)
return 0;
p = s + strlen(s);
while (isspace(p[-1]))
*--p = 0;
len = p - s;
if (slash)
len += strlen(slash);
p = xmalloc(len + 1);
strcpy(p, s);
if (slash)
strcat(p, slash);
uri[0] = p;
return 1;
}
/*
* Read remotes and branches file, fill the push target URI
* list. If there is no command line refspecs, read Push: lines
* to set up the *refspec list as well.
* return the number of push target URIs
*/
static int read_config(const char *repo, const char *uri[MAX_URI])
{
int n;
if (*repo != '/') {
n = get_remotes_uri(repo, uri);
if (n > 0)
return n;
n = get_config_remotes_uri(repo, uri);
if (n > 0)
return n;
n = get_branches_uri(repo, uri);
if (n > 0)
return n;
}
uri[0] = repo;
return 1;
}
static int do_push(const char *repo)
{
const char *uri[MAX_URI];
int i, n;
int remote;
const char **argv;
int argc;
n = read_config(repo, uri);
if (n <= 0)
die("bad repository '%s'", repo);
argv = xmalloc((refspec_nr + 10) * sizeof(char *));
argv[0] = "dummy-send-pack";
argc = 1;
if (all)
argv[argc++] = "--all";
if (force)
argv[argc++] = "--force";
if (execute)
argv[argc++] = execute;
if (thin)
argv[argc++] = "--thin";
remote = argc;
argv[argc++] = "dummy-remote";
while (refspec_nr--)
argv[argc++] = *refspec++;
argv[argc] = NULL;
for (i = 0; i < n; i++) {
int error;
const char *dest = uri[i];
const char *sender = "git-send-pack";
if (!strncmp(dest, "http://", 7) ||
!strncmp(dest, "https://", 8))
sender = "git-http-push";
argv[0] = sender;
argv[remote] = dest;
error = run_command_v(argc, argv);
if (!error)
continue;
switch (error) {
case -ERR_RUN_COMMAND_FORK:
die("unable to fork for %s", sender);
case -ERR_RUN_COMMAND_EXEC:
die("unable to exec %s", sender);
case -ERR_RUN_COMMAND_WAITPID:
case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
die("%s died with strange error", sender);
default:
return -error;
}
}
return 0;
}
int cmd_push(int argc, const char **argv, char **envp)
{
int i;
const char *repo = "origin"; // default repository
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (arg[0] != '-') {
repo = arg;
i++;
break;
}
if (!strcmp(arg, "--all")) {
all = 1;
continue;
}
if (!strcmp(arg, "--tags")) {
tags = 1;
continue;
}
if (!strcmp(arg, "--force")) {
force = 1;
continue;
}
if (!strcmp(arg, "--thin")) {
thin = 1;
continue;
}
if (!strcmp(arg, "--no-thin")) {
thin = 0;
continue;
}
if (!strncmp(arg, "--exec=", 7)) {
execute = arg;
continue;
}
usage(push_usage);
}
set_refspecs(argv + i, argc - i);
return do_push(repo);
}

View File

@ -19,6 +19,10 @@ extern int cmd_version(int argc, const char **argv, char **envp);
extern int cmd_whatchanged(int argc, const char **argv, char **envp); extern int cmd_whatchanged(int argc, const char **argv, char **envp);
extern int cmd_show(int argc, const char **argv, char **envp); extern int cmd_show(int argc, const char **argv, char **envp);
extern int cmd_log(int argc, const char **argv, char **envp); extern int cmd_log(int argc, const char **argv, char **envp);
extern int cmd_diff(int argc, const char **argv, char **envp);
extern int cmd_format_patch(int argc, const char **argv, char **envp); extern int cmd_format_patch(int argc, const char **argv, char **envp);
extern int cmd_count_objects(int argc, const char **argv, char **envp);
extern int cmd_push(int argc, const char **argv, char **envp);
#endif #endif

View File

@ -134,6 +134,8 @@ extern const char *setup_git_directory_gently(int *);
extern const char *setup_git_directory(void); extern const char *setup_git_directory(void);
extern const char *prefix_path(const char *prefix, int len, const char *path); extern const char *prefix_path(const char *prefix, int len, const char *path);
extern const char *prefix_filename(const char *prefix, int len, const char *path); extern const char *prefix_filename(const char *prefix, int len, const char *path);
extern void verify_filename(const char *prefix, const char *name);
extern void verify_non_filename(const char *prefix, const char *name);
#define alloc_nr(x) (((x)+16)*3/2) #define alloc_nr(x) (((x)+16)*3/2)
@ -167,7 +169,7 @@ extern void rollback_index_file(struct cache_file *);
/* Environment bits from configuration mechanism */ /* Environment bits from configuration mechanism */
extern int trust_executable_bit; extern int trust_executable_bit;
extern int assume_unchanged; extern int assume_unchanged;
extern int only_use_symrefs; extern int prefer_symlink_refs;
extern int warn_ambiguous_refs; extern int warn_ambiguous_refs;
extern int diff_rename_limit_default; extern int diff_rename_limit_default;
extern int shared_repository; extern int shared_repository;

View File

@ -269,12 +269,16 @@ int main(int argc, char **argv)
/* Check out named files first */ /* Check out named files first */
for ( ; i < argc; i++) { for ( ; i < argc; i++) {
const char *arg = argv[i]; const char *arg = argv[i];
const char *p;
if (all) if (all)
die("git-checkout-index: don't mix '--all' and explicit filenames"); die("git-checkout-index: don't mix '--all' and explicit filenames");
if (read_from_stdin) if (read_from_stdin)
die("git-checkout-index: don't mix '--stdin' and explicit filenames"); die("git-checkout-index: don't mix '--stdin' and explicit filenames");
checkout_file(prefix_path(prefix, prefix_length, arg)); p = prefix_path(prefix, prefix_length, arg);
checkout_file(p);
if (p != arg)
free((char*)p);
} }
if (read_from_stdin) { if (read_from_stdin) {
@ -284,6 +288,8 @@ int main(int argc, char **argv)
strbuf_init(&buf); strbuf_init(&buf);
while (1) { while (1) {
char *path_name; char *path_name;
const char *p;
read_line(&buf, stdin, line_termination); read_line(&buf, stdin, line_termination);
if (buf.eof) if (buf.eof)
break; break;
@ -291,7 +297,10 @@ int main(int argc, char **argv)
path_name = unquote_c_style(buf.buf, NULL); path_name = unquote_c_style(buf.buf, NULL);
else else
path_name = buf.buf; path_name = buf.buf;
checkout_file(prefix_path(prefix, prefix_length, path_name)); p = prefix_path(prefix, prefix_length, path_name);
checkout_file(p);
if (p != path_name)
free((char *)p);
if (path_name != buf.buf) if (path_name != buf.buf)
free(path_name); free(path_name);
} }

View File

@ -831,15 +831,16 @@ void show_combined_diff(struct combine_diff_path *p,
} }
} }
void diff_tree_combined_merge(const unsigned char *sha1, void diff_tree_combined(const unsigned char *sha1,
int dense, struct rev_info *rev) const unsigned char parent[][20],
int num_parent,
int dense,
struct rev_info *rev)
{ {
struct diff_options *opt = &rev->diffopt; struct diff_options *opt = &rev->diffopt;
struct commit *commit = lookup_commit(sha1);
struct diff_options diffopts; struct diff_options diffopts;
struct commit_list *parents;
struct combine_diff_path *p, *paths = NULL; struct combine_diff_path *p, *paths = NULL;
int num_parent, i, num_paths; int i, num_paths;
int do_diffstat; int do_diffstat;
do_diffstat = (opt->output_format == DIFF_FORMAT_DIFFSTAT || do_diffstat = (opt->output_format == DIFF_FORMAT_DIFFSTAT ||
@ -849,17 +850,8 @@ void diff_tree_combined_merge(const unsigned char *sha1,
diffopts.with_stat = 0; diffopts.with_stat = 0;
diffopts.recursive = 1; 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 */ /* find set of paths that everybody touches */
for (parents = commit->parents, i = 0; for (i = 0; i < num_parent; i++) {
parents;
parents = parents->next, i++) {
struct commit *parent = parents->item;
/* show stat against the first parent even /* show stat against the first parent even
* when doing combined diff. * when doing combined diff.
*/ */
@ -867,8 +859,7 @@ void diff_tree_combined_merge(const unsigned char *sha1,
diffopts.output_format = DIFF_FORMAT_DIFFSTAT; diffopts.output_format = DIFF_FORMAT_DIFFSTAT;
else else
diffopts.output_format = DIFF_FORMAT_NO_OUTPUT; diffopts.output_format = DIFF_FORMAT_NO_OUTPUT;
diff_tree_sha1(parent->object.sha1, commit->object.sha1, "", diff_tree_sha1(parent[i], sha1, "", &diffopts);
&diffopts);
diffcore_std(&diffopts); diffcore_std(&diffopts);
paths = intersect_paths(paths, i, num_parent); paths = intersect_paths(paths, i, num_parent);
@ -907,3 +898,25 @@ void diff_tree_combined_merge(const unsigned char *sha1,
free(tmp); free(tmp);
} }
} }
void diff_tree_combined_merge(const unsigned char *sha1,
int dense, struct rev_info *rev)
{
int num_parent;
const unsigned char (*parent)[20];
struct commit *commit = lookup_commit(sha1);
struct commit_list *parents;
/* count parents */
for (parents = commit->parents, num_parent = 0;
parents;
parents = parents->next, num_parent++)
; /* nothing */
parent = xmalloc(num_parent * sizeof(*parent));
for (parents = commit->parents, num_parent = 0;
parents;
parents = parents->next, num_parent++)
memcpy(parent + num_parent, parents->item->object.sha1, 20);
diff_tree_combined(sha1, parent, num_parent, dense, rev);
}

View File

@ -45,14 +45,13 @@ static void add_buffer(char **bufp, unsigned int *sizep, const char *fmt, ...)
static void check_valid(unsigned char *sha1, const char *expect) static void check_valid(unsigned char *sha1, const char *expect)
{ {
void *buf;
char type[20]; char type[20];
unsigned long size;
buf = read_sha1_file(sha1, type, &size); if (sha1_object_info(sha1, type, NULL))
if (!buf || strcmp(type, expect)) die("%s is not a valid object", sha1_to_hex(sha1));
die("%s is not a valid '%s' object", sha1_to_hex(sha1), expect); if (expect && strcmp(type, expect))
free(buf); die("%s is not a valid '%s' object", sha1_to_hex(sha1),
expect);
} }
/* /*
@ -92,7 +91,7 @@ int main(int argc, char **argv)
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(argv[1], tree_sha1) < 0)
usage(commit_tree_usage); usage(commit_tree_usage);
check_valid(tree_sha1, tree_type); check_valid(tree_sha1, tree_type);

View File

@ -60,6 +60,12 @@ static char *parse_value(void)
space = 1; space = 1;
continue; continue;
} }
if (!quote) {
if (c == ';' || c == '#') {
comment = 1;
continue;
}
}
if (space) { if (space) {
if (len) if (len)
value[len++] = ' '; value[len++] = ' ';
@ -93,12 +99,6 @@ static char *parse_value(void)
quote = 1-quote; quote = 1-quote;
continue; continue;
} }
if (!quote) {
if (c == ';' || c == '#') {
comment = 1;
continue;
}
}
value[len++] = c; value[len++] = c;
} }
} }
@ -227,8 +227,8 @@ int git_default_config(const char *var, const char *value)
return 0; return 0;
} }
if (!strcmp(var, "core.symrefsonly")) { if (!strcmp(var, "core.prefersymlinkrefs")) {
only_use_symrefs = git_config_bool(var, value); prefer_symlink_refs = git_config_bool(var, value);
return 0; return 0;
} }
@ -252,7 +252,7 @@ int git_default_config(const char *var, const char *value)
return 0; return 0;
} }
/* Add other config variables here.. */ /* Add other config variables here and to Documentation/config.txt. */
return 0; return 0;
} }
@ -335,8 +335,11 @@ static int store_aux(const char* key, const char* value)
store.offset[store.seen] = ftell(config_file); store.offset[store.seen] = ftell(config_file);
store.state = KEY_SEEN; store.state = KEY_SEEN;
store.seen++; store.seen++;
} else if(!strncmp(key, store.key, store.baselen)) } else if (strrchr(key, '.') - key == store.baselen &&
!strncmp(key, store.key, store.baselen)) {
store.state = SECTION_SEEN; store.state = SECTION_SEEN;
store.offset[store.seen] = ftell(config_file);
}
} }
return 0; return 0;
} }

2
contrib/colordiff/README Normal file
View File

@ -0,0 +1,2 @@
This is "colordiff" (http://colordiff.sourceforge.net/) by Dave
Ewart <davee@sungate.co.uk>, modified specifically for git.

196
contrib/colordiff/colordiff.perl Executable file
View File

@ -0,0 +1,196 @@
#!/usr/bin/perl -w
#
# $Id: colordiff.pl,v 1.4.2.10 2004/01/04 15:02:59 daveewart Exp $
########################################################################
# #
# ColorDiff - a wrapper/replacment for 'diff' producing #
# colourful output #
# #
# Copyright (C)2002-2004 Dave Ewart (davee@sungate.co.uk) #
# #
########################################################################
# #
# This program 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; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program 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 program; if not, write to the Free Software #
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
# #
########################################################################
use strict;
use Getopt::Long qw(:config pass_through);
use IPC::Open2;
my $app_name = 'colordiff';
my $version = '1.0.4';
my $author = 'Dave Ewart';
my $author_email = 'davee@sungate.co.uk';
my $app_www = 'http://colordiff.sourceforge.net/';
my $copyright = '(C)2002-2004';
my $show_banner = 1;
# ANSI sequences for colours
my %colour;
$colour{white} = "\033[1;37m";
$colour{yellow} = "\033[1;33m";
$colour{green} = "\033[1;32m";
$colour{blue} = "\033[1;34m";
$colour{cyan} = "\033[1;36m";
$colour{red} = "\033[1;31m";
$colour{magenta} = "\033[1;35m";
$colour{black} = "\033[1;30m";
$colour{darkwhite} = "\033[0;37m";
$colour{darkyellow} = "\033[0;33m";
$colour{darkgreen} = "\033[0;32m";
$colour{darkblue} = "\033[0;34m";
$colour{darkcyan} = "\033[0;36m";
$colour{darkred} = "\033[0;31m";
$colour{darkmagenta} = "\033[0;35m";
$colour{darkblack} = "\033[0;30m";
$colour{OFF} = "\033[0;0m";
# Default colours if /etc/colordiffrc or ~/.colordiffrc do not exist
my $plain_text = $colour{OFF};
my $file_old = $colour{red};
my $file_new = $colour{blue};
my $diff_stuff = $colour{magenta};
# Locations for personal and system-wide colour configurations
my $HOME = $ENV{HOME};
my $etcdir = '/etc';
my ($setting, $value);
my @config_files = ("$etcdir/colordiffrc", "$HOME/.colordiffrc");
my $config_file;
foreach $config_file (@config_files) {
if (open(COLORDIFFRC, "<$config_file")) {
while (<COLORDIFFRC>) {
chop;
next if (/^#/ || /^$/);
s/\s+//g;
($setting, $value) = split ('=');
if ($setting eq 'banner') {
if ($value eq 'no') {
$show_banner = 0;
}
next;
}
if (!defined $colour{$value}) {
print "Invalid colour specification ($value) in $config_file\n";
next;
}
if ($setting eq 'plain') {
$plain_text = $colour{$value};
}
elsif ($setting eq 'oldtext') {
$file_old = $colour{$value};
}
elsif ($setting eq 'newtext') {
$file_new = $colour{$value};
}
elsif ($setting eq 'diffstuff') {
$diff_stuff = $colour{$value};
}
else {
print "Unknown option in $etcdir/colordiffrc: $setting\n";
}
}
close COLORDIFFRC;
}
}
# colordiff specfic options here. Need to pre-declare if using variables
GetOptions(
"no-banner" => sub { $show_banner = 0 },
"plain-text=s" => \&set_color,
"file-old=s" => \&set_color,
"file-new=s" => \&set_color,
"diff-stuff=s" => \&set_color
);
if ($show_banner == 1) {
print STDERR "$app_name $version ($app_www)\n";
print STDERR "$copyright $author, $author_email\n\n";
}
if (defined $ARGV[0]) {
# More reliable way of pulling in arguments
open2(\*INPUTSTREAM, undef, "git", "diff", @ARGV);
}
else {
*INPUTSTREAM = \*STDIN;
}
my $record;
my $nrecs = 0;
my $inside_file_old = 1;
my $nparents = undef;
while (<INPUTSTREAM>) {
$nrecs++;
if (/^(\@\@+) -[-+0-9, ]+ \1/) {
print "$diff_stuff";
$nparents = length($1) - 1;
}
elsif (/^diff -/ || /^index / ||
/^old mode / || /^new mode / ||
/^deleted file mode / || /^new file mode / ||
/^similarity index / || /^dissimilarity index / ||
/^copy from / || /^copy to / ||
/^rename from / || /^rename to /) {
$nparents = undef;
print "$diff_stuff";
}
elsif (defined $nparents) {
if ($nparents == 1) {
if (/^\+/) {
print $file_new;
}
elsif (/^-/) {
print $file_old;
}
else {
print $plain_text;
}
}
elsif (/^ {$nparents}/) {
print "$plain_text";
}
elsif (/^[+ ]{$nparents}/) {
print "$file_new";
}
elsif (/^[- ]{$nparents}/) {
print "$file_old";
}
else {
print $plain_text;
}
}
elsif (/^--- / || /^\+\+\+ /) {
print $diff_stuff;
}
else {
print "$plain_text";
}
s/$/$colour{OFF}/;
print "$_";
}
close INPUTSTREAM;
sub set_color {
my ($type, $color) = @_;
$type =~ s/-/_/;
eval "\$$type = \$colour{$color}";
}

View File

@ -8,7 +8,7 @@ use vars qw/ $AUTHOR $VERSION
$GIT_SVN_INDEX $GIT_SVN $GIT_SVN_INDEX $GIT_SVN
$GIT_DIR $REV_DIR/; $GIT_DIR $REV_DIR/;
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>'; $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
$VERSION = '0.11.0'; $VERSION = '1.0.0';
use Cwd qw/abs_path/; use Cwd qw/abs_path/;
$GIT_DIR = abs_path($ENV{GIT_DIR} || '.git'); $GIT_DIR = abs_path($ENV{GIT_DIR} || '.git');
@ -42,7 +42,8 @@ my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext,
my %cmd = ( my %cmd = (
fetch => [ \&fetch, "Download new revisions from SVN", fetch => [ \&fetch, "Download new revisions from SVN",
{ 'revision|r=s' => \$_revision, %fc_opts } ], { 'revision|r=s' => \$_revision, %fc_opts } ],
init => [ \&init, "Initialize and fetch (import)", { } ], init => [ \&init, "Initialize a repo for tracking" .
" (requires URL argument)", { } ],
commit => [ \&commit, "Commit git revisions to SVN", commit => [ \&commit, "Commit git revisions to SVN",
{ 'stdin|' => \$_stdin, { 'stdin|' => \$_stdin,
'edit|e' => \$_edit, 'edit|e' => \$_edit,
@ -220,7 +221,8 @@ when you have upgraded your tools and habits to use refs/remotes/$GIT_SVN
} }
sub init { sub init {
$SVN_URL = shift or croak "SVN repository location required\n"; $SVN_URL = shift or die "SVN repository location required " .
"as a command-line argument\n";
unless (-d $GIT_DIR) { unless (-d $GIT_DIR) {
sys('git-init-db'); sys('git-init-db');
} }

View File

@ -36,17 +36,22 @@ COMMANDS
-------- --------
init:: init::
Creates an empty git repository with additional metadata Creates an empty git repository with additional metadata
directories for git-svn. The SVN_URL must be specified directories for git-svn. The Subversion URL must be specified
at this point. as a command-line argument.
fetch:: fetch::
Fetch unfetched revisions from the SVN_URL we are tracking. Fetch unfetched revisions from the Subversion URL we are
refs/heads/remotes/git-svn will be updated to the latest revision. tracking. refs/remotes/git-svn will be updated to the
latest revision.
Note: You should never attempt to modify the remotes/git-svn branch Note: You should never attempt to modify the remotes/git-svn
outside of git-svn. Instead, create a branch from remotes/git-svn branch outside of git-svn. Instead, create a branch from
and work on that branch. Use the 'commit' command (see below) remotes/git-svn and work on that branch. Use the 'commit'
to write git commits back to remotes/git-svn. command (see below) to write git commits back to
remotes/git-svn.
See 'Additional Fetch Arguments' if you are interested in
manually joining branches on commit.
commit:: commit::
Commit specified commit or tree objects to SVN. This relies on Commit specified commit or tree objects to SVN. This relies on
@ -62,9 +67,9 @@ rebuild::
tracked with git-svn. Unfortunately, git-clone does not clone tracked with git-svn. Unfortunately, git-clone does not clone
git-svn metadata and the svn working tree that git-svn uses for git-svn metadata and the svn working tree that git-svn uses for
its operations. This rebuilds the metadata so git-svn can its operations. This rebuilds the metadata so git-svn can
resume fetch operations. SVN_URL may be optionally specified if resume fetch operations. A Subversion URL may be optionally
the directory/repository you're tracking has moved or changed specified at the command-line if the directory/repository you're
protocols. tracking has moved or changed protocols.
show-ignore:: show-ignore::
Recursively finds and lists the svn:ignore property on Recursively finds and lists the svn:ignore property on
@ -123,6 +128,24 @@ OPTIONS
repo-config key: svn.l repo-config key: svn.l
repo-config key: svn.findcopiesharder repo-config key: svn.findcopiesharder
-A<filename>::
--authors-file=<filename>::
Syntax is compatible with the files used by git-svnimport and
git-cvsimport:
------------------------------------------------------------------------
loginname = Joe User <user@example.com>
------------------------------------------------------------------------
If this option is specified and git-svn encounters an SVN
committer name that does not exist in the authors-file, git-svn
will abort operation. The user will then have to add the
appropriate entry. Re-running the previous git-svn command
after the authors-file is modified should continue operation.
repo-config key: svn.authors-file
ADVANCED OPTIONS ADVANCED OPTIONS
---------------- ----------------
-b<refname>:: -b<refname>::

View File

@ -535,7 +535,7 @@ static int socksetup(int port, int **socklist_p)
if (set_reuse_addr(sockfd)) { if (set_reuse_addr(sockfd)) {
close(sockfd); close(sockfd);
return 0; /* not fatal */ continue;
} }
if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {

View File

@ -2,11 +2,11 @@
#define DELTA_H #define DELTA_H
/* handling of delta buffers */ /* handling of delta buffers */
extern void *diff_delta(void *from_buf, unsigned long from_size, extern void *diff_delta(const void *from_buf, unsigned long from_size,
void *to_buf, unsigned long to_size, const void *to_buf, unsigned long to_size,
unsigned long *delta_size, unsigned long max_size); unsigned long *delta_size, unsigned long max_size);
extern void *patch_delta(void *src_buf, unsigned long src_size, extern void *patch_delta(void *src_buf, unsigned long src_size,
void *delta_buf, unsigned long delta_size, const void *delta_buf, unsigned long delta_size,
unsigned long *dst_size); unsigned long *dst_size);
/* the smallest possible delta size is 4 bytes */ /* the smallest possible delta size is 4 bytes */

View File

@ -131,8 +131,8 @@ static struct index ** delta_index(const unsigned char *buf,
/* the maximum size for any opcode */ /* the maximum size for any opcode */
#define MAX_OP_SIZE COPYOP_SIZE(0xffffffff, 0xffffffff) #define MAX_OP_SIZE COPYOP_SIZE(0xffffffff, 0xffffffff)
void *diff_delta(void *from_buf, unsigned long from_size, void *diff_delta(const void *from_buf, unsigned long from_size,
void *to_buf, unsigned long to_size, const void *to_buf, unsigned long to_size,
unsigned long *delta_size, unsigned long *delta_size,
unsigned long max_size) unsigned long max_size)
{ {

View File

@ -12,203 +12,43 @@ static const char diff_files_usage[] =
"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<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 rev_info rev;
static int silent = 0;
static int diff_unmerged_stage = 2;
static int combine_merges = 0;
static int dense_combined_merges = 0;
static void show_unmerge(const char *path)
{
diff_unmerge(&rev.diffopt, path);
}
static void show_file(int pfx, struct cache_entry *ce)
{
diff_addremove(&rev.diffopt, pfx, ntohl(ce->ce_mode),
ce->sha1, ce->name, NULL);
}
static void show_modified(int oldmode, int mode,
const unsigned char *old_sha1, const unsigned char *sha1,
char *path)
{
diff_change(&rev.diffopt, oldmode, mode, old_sha1, sha1, path, NULL);
}
int main(int argc, const char **argv) int main(int argc, const char **argv)
{ {
const char **pathspec; struct rev_info rev;
const char *prefix = setup_git_directory(); int silent = 0;
int entries, i;
git_config(git_diff_config); git_config(git_diff_config);
diff_setup(&rev.diffopt); init_revisions(&rev);
rev.abbrev = 0;
argc = setup_revisions(argc, argv, &rev, NULL);
while (1 < argc && argv[1][0] == '-') { while (1 < argc && argv[1][0] == '-') {
if (!strcmp(argv[1], "--")) { if (!strcmp(argv[1], "--base"))
argv++; rev.max_count = 1;
argc--;
break;
}
if (!strcmp(argv[1], "-0"))
diff_unmerged_stage = 0;
else if (!strcmp(argv[1], "-1"))
diff_unmerged_stage = 1;
else if (!strcmp(argv[1], "-2"))
diff_unmerged_stage = 2;
else if (!strcmp(argv[1], "-3"))
diff_unmerged_stage = 3;
else if (!strcmp(argv[1], "--base"))
diff_unmerged_stage = 1;
else if (!strcmp(argv[1], "--ours")) else if (!strcmp(argv[1], "--ours"))
diff_unmerged_stage = 2; rev.max_count = 2;
else if (!strcmp(argv[1], "--theirs")) else if (!strcmp(argv[1], "--theirs"))
diff_unmerged_stage = 3; rev.max_count = 3;
else if (!strcmp(argv[1], "-q")) else if (!strcmp(argv[1], "-q"))
silent = 1; silent = 1;
else if (!strcmp(argv[1], "-r"))
; /* no-op */
else if (!strcmp(argv[1], "-s"))
; /* no-op */
else if (!strcmp(argv[1], "-c"))
combine_merges = 1;
else if (!strcmp(argv[1], "--cc"))
dense_combined_merges = combine_merges = 1;
else {
int diff_opt_cnt;
diff_opt_cnt = diff_opt_parse(&rev.diffopt,
argv+1, argc-1);
if (diff_opt_cnt < 0)
usage(diff_files_usage);
else if (diff_opt_cnt) {
argv += diff_opt_cnt;
argc -= diff_opt_cnt;
continue;
}
else else
usage(diff_files_usage); usage(diff_files_usage);
}
argv++; argc--; argv++; argc--;
} }
if (dense_combined_merges) /*
rev.diffopt.output_format = DIFF_FORMAT_PATCH; * Make sure there are NO revision (i.e. pending object) parameter,
* rev.max_count is reasonable (0 <= n <= 3),
/* Find the directory, and set up the pathspec */ * there is no other revision filtering parameters.
pathspec = get_pathspec(prefix, argv + 1); */
entries = read_cache(); if (rev.pending_objects ||
rev.min_age != -1 || rev.max_age != -1)
if (diff_setup_done(&rev.diffopt) < 0)
usage(diff_files_usage); usage(diff_files_usage);
/* At this point, if argc == 1, then we are doing everything.
* Otherwise argv[1] .. argv[argc-1] have the explicit paths.
*/
if (entries < 0) {
perror("read_cache");
exit(1);
}
for (i = 0; i < entries; i++) {
struct stat st;
unsigned int oldmode, newmode;
struct cache_entry *ce = active_cache[i];
int changed;
if (!ce_path_match(ce, pathspec))
continue;
if (ce_stage(ce)) {
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) {
struct cache_entry *nce = active_cache[i];
int stage;
if (strcmp(ce->name, nce->name))
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 =
canon_mode(mode);
combine.p.parent[stage-2].status =
DIFF_STATUS_MODIFIED;
}
/* diff against the proper unmerged stage */
if (stage == diff_unmerged_stage)
ce = nce;
i++;
}
/* /*
* Compensate for loop update * Backward compatibility wart - "diff-files -s" used to
* defeat the common diff option "-s" which asked for
* DIFF_FORMAT_NO_OUTPUT.
*/ */
i--; if (rev.diffopt.output_format == DIFF_FORMAT_NO_OUTPUT)
rev.diffopt.output_format = DIFF_FORMAT_RAW;
if (combine_merges && num_compare_stages == 2) { return run_diff_files(&rev, silent);
show_combined_diff(&combine.p, 2,
dense_combined_merges,
&rev);
free(combine.p.path);
continue;
}
free(combine.p.path);
/*
* Show the diff for the 'ce' if we found the one
* from the desired stage.
*/
show_unmerge(ce->name);
if (ce_stage(ce) != diff_unmerged_stage)
continue;
}
if (lstat(ce->name, &st) < 0) {
if (errno != ENOENT && errno != ENOTDIR) {
perror(ce->name);
continue;
}
if (silent)
continue;
show_file('-', ce);
continue;
}
changed = ce_match_stat(ce, &st, 0);
if (!changed && !rev.diffopt.find_copies_harder)
continue;
oldmode = ntohl(ce->ce_mode);
newmode = canon_mode(st.st_mode);
if (!trust_executable_bit &&
S_ISREG(newmode) && S_ISREG(oldmode) &&
((newmode ^ oldmode) == 0111))
newmode = oldmode;
show_modified(oldmode, newmode,
ce->sha1, (changed ? null_sha1 : ce->sha1),
ce->name);
}
diffcore_std(&rev.diffopt);
diff_flush(&rev.diffopt);
return 0;
} }

View File

@ -1,166 +1,7 @@
#include "cache.h" #include "cache.h"
#include "tree.h"
#include "diff.h" #include "diff.h"
#include "commit.h"
static int cached_only = 0; #include "revision.h"
static int match_nonexisting = 0;
static struct diff_options diff_options;
/* A file entry went away or appeared */
static void show_file(const char *prefix,
struct cache_entry *ce,
unsigned char *sha1, unsigned int mode)
{
diff_addremove(&diff_options, prefix[0], ntohl(mode),
sha1, ce->name, NULL);
}
static int get_stat_data(struct cache_entry *ce,
unsigned char ** sha1p, unsigned int *modep)
{
unsigned char *sha1 = ce->sha1;
unsigned int mode = ce->ce_mode;
if (!cached_only) {
static unsigned char no_sha1[20];
int changed;
struct stat st;
if (lstat(ce->name, &st) < 0) {
if (errno == ENOENT && match_nonexisting) {
*sha1p = sha1;
*modep = mode;
return 0;
}
return -1;
}
changed = ce_match_stat(ce, &st, 0);
if (changed) {
mode = create_ce_mode(st.st_mode);
if (!trust_executable_bit && S_ISREG(st.st_mode))
mode = ce->ce_mode;
sha1 = no_sha1;
}
}
*sha1p = sha1;
*modep = mode;
return 0;
}
static void show_new_file(struct cache_entry *new)
{
unsigned char *sha1;
unsigned int mode;
/* New file in the index: it might actually be different in
* the working copy.
*/
if (get_stat_data(new, &sha1, &mode) < 0)
return;
show_file("+", new, sha1, mode);
}
static int show_modified(struct cache_entry *old,
struct cache_entry *new,
int report_missing)
{
unsigned int mode, oldmode;
unsigned char *sha1;
if (get_stat_data(new, &sha1, &mode) < 0) {
if (report_missing)
show_file("-", old, old->sha1, old->ce_mode);
return -1;
}
oldmode = old->ce_mode;
if (mode == oldmode && !memcmp(sha1, old->sha1, 20) &&
!diff_options.find_copies_harder)
return 0;
mode = ntohl(mode);
oldmode = ntohl(oldmode);
diff_change(&diff_options, oldmode, mode,
old->sha1, sha1, old->name, NULL);
return 0;
}
static int diff_cache(struct cache_entry **ac, int entries, const char **pathspec)
{
while (entries) {
struct cache_entry *ce = *ac;
int same = (entries > 1) && ce_same_name(ce, ac[1]);
if (!ce_path_match(ce, pathspec))
goto skip_entry;
switch (ce_stage(ce)) {
case 0:
/* No stage 1 entry? That means it's a new file */
if (!same) {
show_new_file(ce);
break;
}
/* Show difference between old and new */
show_modified(ac[1], ce, 1);
break;
case 1:
/* No stage 3 (merge) entry? That means it's been deleted */
if (!same) {
show_file("-", ce, ce->sha1, ce->ce_mode);
break;
}
/* We come here with ce pointing at stage 1
* (original tree) and ac[1] pointing at stage
* 3 (unmerged). show-modified with
* report-missing set to false does not say the
* file is deleted but reports true if work
* tree does not have it, in which case we
* fall through to report the unmerged state.
* Otherwise, we show the differences between
* the original tree and the work tree.
*/
if (!cached_only && !show_modified(ce, ac[1], 0))
break;
/* fallthru */
case 3:
diff_unmerge(&diff_options, ce->name);
break;
default:
die("impossible cache entry stage");
}
skip_entry:
/*
* Ignore all the different stages for this file,
* we've handled the relevant cases now.
*/
do {
ac++;
entries--;
} while (entries && ce_same_name(ce, ac[0]));
}
return 0;
}
/*
* This turns all merge entries into "stage 3". That guarantees that
* when we read in the new tree (into "stage 1"), we won't lose sight
* of the fact that we had unmerged entries.
*/
static void mark_merge_entries(void)
{
int i;
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
if (!ce_stage(ce))
continue;
ce->ce_flags |= htons(CE_STAGEMASK);
}
}
static const char diff_cache_usage[] = static const char diff_cache_usage[] =
"git-diff-index [-m] [--cached] " "git-diff-index [-m] [--cached] "
@ -169,85 +10,29 @@ COMMON_DIFF_OPTIONS_HELP;
int main(int argc, const char **argv) int main(int argc, const char **argv)
{ {
const char *tree_name = NULL; struct rev_info rev;
unsigned char sha1[20]; int cached = 0;
const char *prefix = setup_git_directory();
const char **pathspec = NULL;
struct tree *tree;
int ret;
int allow_options = 1;
int i; int i;
git_config(git_diff_config); git_config(git_diff_config);
diff_setup(&diff_options); init_revisions(&rev);
rev.abbrev = 0;
argc = setup_revisions(argc, argv, &rev, NULL);
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
const char *arg = argv[i]; const char *arg = argv[i];
int diff_opt_cnt;
if (!allow_options || *arg != '-') { if (!strcmp(arg, "--cached"))
if (tree_name) cached = 1;
break; else
tree_name = arg; usage(diff_cache_usage);
continue;
} }
if (!strcmp(arg, "--")) {
allow_options = 0;
continue;
}
if (!strcmp(arg, "-r")) {
/* We accept the -r flag just to look like git-diff-tree */
continue;
}
if (!strcmp(arg, "--cc"))
/* /*
* I _think_ "diff-index --cached HEAD" with an * Make sure there is one revision (i.e. pending object),
* unmerged index could show something else * and there is no revision filtering parameters.
* later, but pretend --cc is the same as -p for
* now. "git diff" uses --cc by default.
*/ */
argv[i] = arg = "-p"; if (!rev.pending_objects || rev.pending_objects->next ||
diff_opt_cnt = diff_opt_parse(&diff_options, argv + i, rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
argc - i);
if (diff_opt_cnt < 0)
usage(diff_cache_usage); usage(diff_cache_usage);
else if (diff_opt_cnt) { return run_diff_index(&rev, cached);
i += diff_opt_cnt - 1;
continue;
}
if (!strcmp(arg, "-m")) {
match_nonexisting = 1;
continue;
}
if (!strcmp(arg, "--cached")) {
cached_only = 1;
continue;
}
usage(diff_cache_usage);
}
pathspec = get_pathspec(prefix, argv + i);
if (diff_setup_done(&diff_options) < 0)
usage(diff_cache_usage);
if (!tree_name || get_sha1(tree_name, sha1))
usage(diff_cache_usage);
read_cache();
mark_merge_entries();
tree = parse_tree_indirect(sha1);
if (!tree)
die("bad tree object %s", tree_name);
if (read_tree(tree, 1, pathspec))
die("unable to read tree object %s", tree_name);
ret = diff_cache(active_cache, active_nr, pathspec);
diffcore_std(&diff_options);
diff_flush(&diff_options);
return ret;
} }

1988
diff-lib.c

File diff suppressed because it is too large Load Diff

1803
diff.c Normal file

File diff suppressed because it is too large Load Diff

11
diff.h
View File

@ -28,10 +28,11 @@ struct diff_options {
with_raw:1, with_raw:1,
with_stat:1, with_stat:1,
tree_in_recursive:1, tree_in_recursive:1,
full_index:1; full_index:1,
silent_on_remove:1,
find_copies_harder:1;
int break_opt; int break_opt;
int detect_rename; int detect_rename;
int find_copies_harder;
int line_termination; int line_termination;
int output_format; int output_format;
int pickaxe_opts; int pickaxe_opts;
@ -74,6 +75,8 @@ struct combine_diff_path {
extern void show_combined_diff(struct combine_diff_path *elem, int num_parent, extern void show_combined_diff(struct combine_diff_path *elem, int num_parent,
int dense, struct rev_info *); int dense, struct rev_info *);
extern void diff_tree_combined(const unsigned char *sha1, const unsigned char parent[][20], int num_parent, int dense, struct rev_info *rev);
extern void diff_tree_combined_merge(const unsigned char *sha1, int, struct rev_info *); extern void diff_tree_combined_merge(const unsigned char *sha1, int, struct rev_info *);
extern void diff_addremove(struct diff_options *, extern void diff_addremove(struct diff_options *,
@ -168,4 +171,8 @@ extern void diff_flush(struct diff_options*);
extern const char *diff_unique_abbrev(const unsigned char *, int); extern const char *diff_unique_abbrev(const unsigned char *, int);
extern int run_diff_files(struct rev_info *revs, int silent_on_removed);
extern int run_diff_index(struct rev_info *revs, int cached);
#endif /* DIFF_H */ #endif /* DIFF_H */

View File

@ -13,7 +13,7 @@ char git_default_email[MAX_GITNAME];
char git_default_name[MAX_GITNAME]; char git_default_name[MAX_GITNAME];
int trust_executable_bit = 1; int trust_executable_bit = 1;
int assume_unchanged = 0; int assume_unchanged = 0;
int only_use_symrefs = 0; int prefer_symlink_refs = 0;
int warn_ambiguous_refs = 1; int warn_ambiguous_refs = 1;
int repository_format_version = 0; int repository_format_version = 0;
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8"; char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";

View File

@ -14,6 +14,26 @@ stop_here () {
exit 1 exit 1
} }
stop_here_user_resolve () {
cmdline=$(basename $0)
if test '' != "$interactive"
then
cmdline="$cmdline -i"
fi
if test '' != "$threeway"
then
cmdline="$cmdline -3"
fi
if test '.dotest' != "$dotest"
then
cmdline="$cmdline -d=$dotest"
fi
echo "When you have resolved this problem run \"$cmdline --resolved\"."
echo "If you would prefer to skip this patch, instead run \"$cmdline --skip\"."
stop_here $1
}
go_next () { go_next () {
rm -f "$dotest/$msgnum" "$dotest/msg" "$dotest/msg-clean" \ rm -f "$dotest/$msgnum" "$dotest/msg" "$dotest/msg-clean" \
"$dotest/patch" "$dotest/info" "$dotest/patch" "$dotest/info"
@ -374,7 +394,14 @@ do
if test '' = "$changed" if test '' = "$changed"
then then
echo "No changes - did you forget update-index?" echo "No changes - did you forget update-index?"
stop_here $this stop_here_user_resolve $this
fi
unmerged=$(git-ls-files -u)
if test -n "$unmerged"
then
echo "You still have unmerged paths in your index"
echo "did you forget update-index?"
stop_here_user_resolve $this
fi fi
apply_status=0 apply_status=0
;; ;;
@ -400,7 +427,7 @@ do
if test $apply_status != 0 if test $apply_status != 0
then then
echo Patch failed at $msgnum. echo Patch failed at $msgnum.
stop_here $this stop_here_user_resolve $this
fi fi
if test -x "$GIT_DIR"/hooks/pre-applypatch if test -x "$GIT_DIR"/hooks/pre-applypatch

View File

@ -10,9 +10,10 @@ use warnings;
use strict; use strict;
use Getopt::Long; use Getopt::Long;
use POSIX qw(strftime gmtime); use POSIX qw(strftime gmtime);
use File::Basename qw(basename dirname);
sub usage() { sub usage() {
print STDERR 'Usage: ${\basename $0} [-s] [-S revs-file] file [ revision ] print STDERR "Usage: ${\basename $0} [-s] [-S revs-file] file [ revision ]
-l, --long -l, --long
Show long rev (Defaults off) Show long rev (Defaults off)
-t, --time -t, --time
@ -23,7 +24,7 @@ sub usage() {
Use revs from revs-file instead of calling git-rev-list Use revs from revs-file instead of calling git-rev-list
-h, --help -h, --help
This message. This message.
'; ";
exit(1); exit(1);
} }
@ -35,7 +36,7 @@ my $rc = GetOptions( "long|l" => \$longrev,
"help|h" => \$help, "help|h" => \$help,
"rename|r" => \$rename, "rename|r" => \$rename,
"rev-file|S=s" => \$rev_file); "rev-file|S=s" => \$rev_file);
if (!$rc or $help) { if (!$rc or $help or !@ARGV) {
usage(); usage();
} }
@ -208,6 +209,9 @@ sub find_parent_renames {
while (my $change = <$patch>) { while (my $change = <$patch>) {
chomp $change; chomp $change;
my $filename = <$patch>; my $filename = <$patch>;
if (!defined $filename) {
next;
}
chomp $filename; chomp $filename;
if ($change =~ m/^[AMD]$/ ) { if ($change =~ m/^[AMD]$/ ) {

View File

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
USAGE='[(-d | -D) <branchname>] | [[-f] <branchname> [<start-point>]]' USAGE='[(-d | -D) <branchname>] | [[-f] <branchname> [<start-point>]] | -r'
LONG_USAGE='If no arguments, show available branches and mark current branch with a star. LONG_USAGE='If no arguments, show available branches and mark current branch with a star.
If one argument, create a new branch <branchname> based off of current HEAD. If one argument, create a new branch <branchname> based off of current HEAD.
If two arguments, create a new branch <branchname> based off of <start-point>.' If two arguments, create a new branch <branchname> based off of <start-point>.'

View File

@ -1,31 +0,0 @@
#!/bin/sh
#
# Copyright (c) 2005 Junio C Hamano
#
GIT_DIR=`git-rev-parse --git-dir` || exit $?
dc </dev/null 2>/dev/null || {
# This is not a real DC at all -- it just knows how
# this script feeds DC and does the computation itself.
dc () {
while read a b
do
case $a,$b in
0,) acc=0 ;;
*,+) acc=$(($acc + $a)) ;;
p,) echo "$acc" ;;
esac
done
}
}
echo $(find "$GIT_DIR/objects"/?? -type f -print 2>/dev/null | wc -l) objects, \
$({
echo 0
# "no-such" is to help Darwin folks by not using xargs -r.
find "$GIT_DIR/objects"/?? -type f -print 2>/dev/null |
xargs du -k "$GIT_DIR/objects/no-such" 2>/dev/null |
sed -e 's/[ ].*/ +/'
echo p
} | dc) kilobytes

View File

@ -88,7 +88,7 @@ my $TEMP_DIR = tempdir( CLEANUP => 1 );
$log->debug("Temporary directory is '$TEMP_DIR'"); $log->debug("Temporary directory is '$TEMP_DIR'");
# if we are called with a pserver argument, # if we are called with a pserver argument,
# deal with the authentication cat before entereing the # deal with the authentication cat before entering the
# main loop # main loop
if (@ARGV && $ARGV[0] eq 'pserver') { if (@ARGV && $ARGV[0] eq 'pserver') {
my $line = <STDIN>; chomp $line; my $line = <STDIN>; chomp $line;
@ -117,7 +117,7 @@ while (<STDIN>)
{ {
chomp; chomp;
# Check to see if we've seen this method, and call appropiate function. # Check to see if we've seen this method, and call appropriate function.
if ( /^([\w-]+)(?:\s+(.*))?$/ and defined($methods->{$1}) ) if ( /^([\w-]+)(?:\s+(.*))?$/ and defined($methods->{$1}) )
{ {
# use the $methods hash to call the appropriate sub for this command # use the $methods hash to call the appropriate sub for this command
@ -171,11 +171,11 @@ sub req_Root
return 0; return 0;
} }
my @gitvars = `git-var -l`; my @gitvars = `git-repo-config -l`;
if ($?) { if ($?) {
print "E problems executing git-var on the server -- this is not a git repository or the PATH is not set correcly.\n"; print "E problems executing git-repo-config on the server -- this is not a git repository or the PATH is not set correctly.\n";
print "E \n"; print "E \n";
print "error 1 - problem executing git-var\n"; print "error 1 - problem executing git-repo-config\n";
return 0; return 0;
} }
foreach my $line ( @gitvars ) foreach my $line ( @gitvars )
@ -224,7 +224,7 @@ sub req_Globaloption
sub req_Validresponses sub req_Validresponses
{ {
my ( $cmd, $data ) = @_; my ( $cmd, $data ) = @_;
$log->debug("req_Validrepsonses : $data"); $log->debug("req_Validresponses : $data");
# TODO : re-enable this, currently it's not particularly useful # TODO : re-enable this, currently it's not particularly useful
#$state->{validresponses} = [ split /\s+/, $data ]; #$state->{validresponses} = [ split /\s+/, $data ];
@ -733,7 +733,7 @@ sub req_update
argsplit("update"); argsplit("update");
# #
# It may just be a client exploring the available heads/modukles # It may just be a client exploring the available heads/modules
# in that case, list them as top level directories and leave it # in that case, list them as top level directories and leave it
# at that. Eclipse uses this technique to offer you a list of # at that. Eclipse uses this technique to offer you a list of
# projects (heads in this case) to checkout. # projects (heads in this case) to checkout.
@ -1731,7 +1731,7 @@ sub transmitfile
} }
# This method takes a file name, and returns ( $dirpart, $filepart ) which # This method takes a file name, and returns ( $dirpart, $filepart ) which
# refers to the directory porition and the file portion of the filename # refers to the directory portion and the file portion of the filename
# respectively # respectively
sub filenamesplit sub filenamesplit
{ {
@ -1790,7 +1790,7 @@ Log::Log4perl
=head2 new =head2 new
Creates a new log object, optionally you can specify a filename here to Creates a new log object, optionally you can specify a filename here to
indicate the file to log to. If no log file is specified, you can specifiy one indicate the file to log to. If no log file is specified, you can specify one
later with method setfile, or indicate you no longer want logging with method later with method setfile, or indicate you no longer want logging with method
nofile. nofile.
@ -2076,14 +2076,15 @@ sub update
# TODO: log processing is memory bound # TODO: log processing is memory bound
# if we can parse into a 2nd file that is in reverse order # if we can parse into a 2nd file that is in reverse order
# we can probably do something really efficient # we can probably do something really efficient
my @git_log_params = ('--parents', '--topo-order'); my @git_log_params = ('--pretty', '--parents', '--topo-order');
if (defined $lastcommit) { if (defined $lastcommit) {
push @git_log_params, "$lastcommit..$self->{module}"; push @git_log_params, "$lastcommit..$self->{module}";
} else { } else {
push @git_log_params, $self->{module}; push @git_log_params, $self->{module};
} }
open(GITLOG, '-|', 'git-log', @git_log_params) or die "Cannot call git-log: $!"; # git-rev-list is the backend / plumbing version of git-log
open(GITLOG, '-|', 'git-rev-list', @git_log_params) or die "Cannot call git-rev-list: $!";
my @commits; my @commits;
@ -2595,7 +2596,7 @@ sub in_array
=head2 safe_pipe_capture =head2 safe_pipe_capture
an alterative to `command` that allows input to be passed as an array an alternative to `command` that allows input to be passed as an array
to work around shell problems with weird characters in arguments to work around shell problems with weird characters in arguments
=cut =cut

View File

@ -1,74 +0,0 @@
#!/bin/sh
#
# Copyright (c) 2005 Linus Torvalds
# Copyright (c) 2005 Junio C Hamano
USAGE='[ --diff-options ] <ent>{0,2} [<path>...]'
SUBDIRECTORY_OK='Yes'
. git-sh-setup
rev=$(git-rev-parse --revs-only --no-flags --sq "$@") || exit
flags=$(git-rev-parse --no-revs --flags --sq "$@")
files=$(git-rev-parse --no-revs --no-flags --sq "$@")
# I often say 'git diff --cached -p' and get scolded by git-diff-files, but
# obviously I mean 'git diff --cached -p HEAD' in that case.
case "$rev" in
'')
case " $flags " in
*" '--cached' "*)
rev='HEAD '
;;
esac
esac
# If we have -[123] --ours --theirs --base, don't do --cc by default.
case " $flags " in
*" '-"[123]"' "* | *" '--ours' "* | *" '--base' "* | *" '--theirs' "*)
cc_or_p=-p ;;
*)
cc_or_p=--cc ;;
esac
# If we do not have --name-status, --name-only, -r, -c or --stat,
# default to --cc.
case " $flags " in
*" '--name-status' "* | *" '--name-only' "* | *" '-r' "* | *" '-c' "* | \
*" '--stat' "*)
;;
*)
flags="$flags'$cc_or_p' " ;;
esac
# If we do not have -B, -C, -r, nor -p, default to -M.
case " $flags " in
*" '-"[BCMrp]* | *" '--find-copies-harder' "*)
;; # something like -M50.
*)
flags="$flags'-M' " ;;
esac
case "$rev" in
?*' '?*' '?*)
usage
;;
?*' '^?*)
begin=$(expr "$rev" : '.*^.\([0-9a-f]*\).*') &&
end=$(expr "$rev" : '.\([0-9a-f]*\). .*') || exit
cmd="git-diff-tree $flags $begin $end -- $files"
;;
?*' '?*)
cmd="git-diff-tree $flags $rev -- $files"
;;
?*' ')
cmd="git-diff-index $flags $rev -- $files"
;;
'')
cmd="git-diff-files $flags -- $files"
;;
*)
usage
;;
esac
eval "$cmd"

View File

@ -270,12 +270,20 @@ fetch_main () {
if [ -n "$GIT_SSL_NO_VERIFY" ]; then if [ -n "$GIT_SSL_NO_VERIFY" ]; then
curl_extra_args="-k" curl_extra_args="-k"
fi fi
max_depth=5
depth=0
head="ref: $remote_name"
while (expr "z$head" : "zref:" && expr $depth \< $max_depth) >/dev/null
do
remote_name_quoted=$(perl -e ' remote_name_quoted=$(perl -e '
my $u = $ARGV[0]; my $u = $ARGV[0];
$u =~ s/^ref:\s*//;
$u =~ s{([^-a-zA-Z0-9/.])}{sprintf"%%%02x",ord($1)}eg; $u =~ s{([^-a-zA-Z0-9/.])}{sprintf"%%%02x",ord($1)}eg;
print "$u"; print "$u";
' "$remote_name") ' "$head")
head=$(curl -nsfL $curl_extra_args "$remote/$remote_name_quoted") && head=$(curl -nsfL $curl_extra_args "$remote/$remote_name_quoted")
depth=$( expr \( $depth + 1 \) )
done
expr "z$head" : "z$_x40\$" >/dev/null || expr "z$head" : "z$_x40\$" >/dev/null ||
die "Failed to fetch $remote_name from $remote" die "Failed to fetch $remote_name from $remote"
echo >&2 Fetching "$remote_name from $remote" using http echo >&2 Fetching "$remote_name from $remote" using http

View File

@ -205,11 +205,10 @@ sub show_date {
} }
my $t = $time + $minutes * 60; my $t = $time + $minutes * 60;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime($t); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime($t);
return sprintf("%s %s %d %02d:%02d:%02d %d %+05d", return sprintf("%s, %d %s %d %02d:%02d:%02d %+05d",
$weekday_names[$wday], $weekday_names[$wday], $mday,
$month_names[$mon], $month_names[$mon], $year+1900,
$mday, $hour, $min, $sec, $hour, $min, $sec, $tz);
$year+1900, $tz);
} }
print "From nobody Mon Sep 17 00:00:00 2001\n"; print "From nobody Mon Sep 17 00:00:00 2001\n";

View File

@ -4,37 +4,51 @@
# #
USAGE='[--onto <newbase>] <upstream> [<branch>]' USAGE='[--onto <newbase>] <upstream> [<branch>]'
LONG_USAGE='git-rebase applies to <upstream> (or optionally to <newbase>) commits LONG_USAGE='git-rebase replaces <branch> with a new branch of the
from <branch> that do not appear in <upstream>. When <branch> is not same name. When the --onto option is provided the new branch starts
specified it defaults to the current branch (HEAD). out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
It then attempts to create a new commit for each commit from the original
<branch> that does not exist in the <upstream> branch.
When git-rebase is complete, <branch> will be updated to point to the It is possible that a merge failure will prevent this process from being
newly created line of commit objects, so the previous line will not be completely automatic. You will have to resolve any such merge failure
accessible unless there are other references to it already. and run git-rebase --continue. If you can not resolve the merge failure,
running git-rebase --abort will restore the original <branch> and remove
the working files found in the .dotest directory.
Assuming the following history: Note that if <branch> is not specified on the command line, the
currently checked out branch is used. You must be in the top
directory of your project to start (or continue) a rebase.
A---B---C topic Example: git-rebase master~1 topic
/
D---E---F---G master
The result of the following command: A---B---C topic A'\''--B'\''--C'\'' topic
/ --> /
git-rebase --onto master~1 master topic D---E---F---G master D---E---F---G master
would be:
A'\''--B'\''--C'\'' topic
/
D---E---F---G master
' '
. git-sh-setup . git-sh-setup
unset newbase unset newbase
while case "$#" in 0) break ;; esac while case "$#" in 0) break ;; esac
do do
case "$1" in case "$1" in
--continue)
diff=$(git-diff-files)
case "$diff" in
?*) echo "You must edit all merge conflicts and then"
echo "mark them as resolved using git update-index"
exit 1
;;
esac
git am --resolved --3way
exit
;;
--abort)
[ -d .dotest ] || die "No rebase in progress?"
git reset --hard ORIG_HEAD
rm -r .dotest
exit
;;
--onto) --onto)
test 2 -le "$#" || usage test 2 -le "$#" || usage
newbase="$2" newbase="$2"
@ -107,7 +121,7 @@ onto=$(git-rev-parse --verify "${onto_name}^0") || exit
# Check if we are already based on $onto, but this should be # Check if we are already based on $onto, but this should be
# done only when upstream and onto are the same. # done only when upstream and onto are the same.
if test "$upstream" = "onto" if test "$upstream" = "$onto"
then then
mb=$(git-merge-base "$onto" "$branch") mb=$(git-merge-base "$onto" "$branch")
if test "$mb" = "$onto" if test "$mb" = "$onto"

View File

@ -291,6 +291,13 @@ sub send_message
my $to = join (",\n\t", @recipients); my $to = join (",\n\t", @recipients);
@recipients = unique_email_list(@recipients,@cc); @recipients = unique_email_list(@recipients,@cc);
my $date = strftime('%a, %d %b %Y %H:%M:%S %z', localtime($time++)); my $date = strftime('%a, %d %b %Y %H:%M:%S %z', localtime($time++));
my $gitversion = '@@GIT_VERSION@@';
if ($gitversion =~ m/..GIT_VERSION../) {
$gitversion = `git --version`;
chomp $gitversion;
# keep only what's after the last space
$gitversion =~ s/^.* //;
}
my $header = "From: $from my $header = "From: $from
To: $to To: $to
@ -299,7 +306,7 @@ Subject: $subject
Reply-To: $from Reply-To: $from
Date: $date Date: $date
Message-Id: $message_id Message-Id: $message_id
X-Mailer: git-send-email @@GIT_VERSION@@ X-Mailer: git-send-email $gitversion
"; ";
$header .= "In-Reply-To: $reply_to\n" if $reply_to; $header .= "In-Reply-To: $reply_to\n" if $reply_to;

View File

@ -1,28 +0,0 @@
#!/bin/sh
USAGE='[-p] [--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [-m] [git-diff-tree options] [git-rev-list options]'
SUBDIRECTORY_OK='Yes'
. git-sh-setup
diff_tree_flags=$(git-rev-parse --sq --no-revs --flags "$@") || exit
case "$0" in
*whatchanged)
count=
test -z "$diff_tree_flags" &&
diff_tree_flags=$(git-repo-config --get whatchanged.difftree)
diff_tree_default_flags='-c -M --abbrev' ;;
*show)
count=-n1
test -z "$diff_tree_flags" &&
diff_tree_flags=$(git-repo-config --get show.difftree)
diff_tree_default_flags='--cc --always' ;;
esac
test -z "$diff_tree_flags" &&
diff_tree_flags="$diff_tree_default_flags"
rev_list_args=$(git-rev-parse --sq --default HEAD --revs-only "$@") &&
diff_tree_args=$(git-rev-parse --sq --no-revs --no-flags "$@") &&
eval "git-rev-list $count $rev_list_args" |
eval "git-diff-tree --stdin --pretty -r $diff_tree_flags $diff_tree_args" |
LESS="$LESS -S" ${PAGER:-less}

4
git.c
View File

@ -8,7 +8,6 @@
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <sys/ioctl.h>
#include "git-compat-util.h" #include "git-compat-util.h"
#include "exec_cmd.h" #include "exec_cmd.h"
@ -47,7 +46,10 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "log", cmd_log }, { "log", cmd_log },
{ "whatchanged", cmd_whatchanged }, { "whatchanged", cmd_whatchanged },
{ "show", cmd_show }, { "show", cmd_show },
{ "push", cmd_push },
{ "fmt-patch", cmd_format_patch }, { "fmt-patch", cmd_format_patch },
{ "count-objects", cmd_count_objects },
{ "diff", cmd_diff },
}; };
int i; int i;

1751
gitk

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,15 @@
#include "commit.h" #include "commit.h"
#include "log-tree.h" #include "log-tree.h"
static void show_parents(struct commit *commit, int abbrev)
{
struct commit_list *p;
for (p = commit->parents; p ; p = p->next) {
struct commit *parent = p->item;
printf(" %s", diff_unique_abbrev(parent->object.sha1, abbrev));
}
}
void show_log(struct rev_info *opt, struct log_info *log, const char *sep) void show_log(struct rev_info *opt, struct log_info *log, const char *sep)
{ {
static char this_header[16384]; static char this_header[16384];
@ -15,7 +24,10 @@ void show_log(struct rev_info *opt, struct log_info *log, const char *sep)
opt->loginfo = NULL; opt->loginfo = NULL;
if (!opt->verbose_header) { if (!opt->verbose_header) {
puts(sha1_to_hex(commit->object.sha1)); fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), stdout);
if (opt->parents)
show_parents(commit, abbrev_commit);
putchar('\n');
return; return;
} }
@ -57,6 +69,8 @@ void show_log(struct rev_info *opt, struct log_info *log, const char *sep)
printf("%s%s", printf("%s%s",
opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ", opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ",
diff_unique_abbrev(commit->object.sha1, abbrev_commit)); diff_unique_abbrev(commit->object.sha1, abbrev_commit));
if (opt->parents)
show_parents(commit, abbrev_commit);
if (parent) if (parent)
printf(" (from %s)", printf(" (from %s)",
diff_unique_abbrev(parent->object.sha1, diff_unique_abbrev(parent->object.sha1,

View File

@ -24,16 +24,14 @@ static const char *sha1_to_hex_zero(const unsigned char *sha1)
static void resolve(const char *base, struct name_entry *branch1, struct name_entry *result) static void resolve(const char *base, struct name_entry *branch1, struct name_entry *result)
{ {
char branch1_sha1[50];
/* If it's already branch1, don't bother showing it */ /* If it's already branch1, don't bother showing it */
if (!branch1) if (!branch1)
return; return;
memcpy(branch1_sha1, sha1_to_hex_zero(branch1->sha1), 41);
printf("0 %06o->%06o %s->%s %s%s\n", printf("0 %06o->%06o %s->%s %s%s\n",
branch1->mode, result->mode, branch1->mode, result->mode,
branch1_sha1, sha1_to_hex_zero(result->sha1), sha1_to_hex_zero(branch1->sha1),
sha1_to_hex_zero(result->sha1),
base, result->path); base, result->path);
} }

View File

@ -29,12 +29,12 @@ static int verify_packfile(struct packed_git *p)
pack_base = p->pack_base; pack_base = p->pack_base;
SHA1_Update(&ctx, pack_base, pack_size - 20); SHA1_Update(&ctx, pack_base, pack_size - 20);
SHA1_Final(sha1, &ctx); SHA1_Final(sha1, &ctx);
if (memcmp(sha1, index_base + index_size - 40, 20))
return error("Packfile %s SHA1 mismatch with idx",
p->pack_name);
if (memcmp(sha1, pack_base + pack_size - 20, 20)) if (memcmp(sha1, pack_base + pack_size - 20, 20))
return error("Packfile %s SHA1 mismatch with itself", return error("Packfile %s SHA1 mismatch with itself",
p->pack_name); p->pack_name);
if (memcmp(sha1, index_base + index_size - 40, 20))
return error("Packfile %s SHA1 mismatch with idx",
p->pack_name);
/* Make sure everything reachable from idx is valid. Since we /* Make sure everything reachable from idx is valid. Since we
* have verified that nr_objects matches between idx and pack, * have verified that nr_objects matches between idx and pack,

View File

@ -1032,12 +1032,6 @@ static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_de
max_depth -= cur_entry->delta_limit; max_depth -= cur_entry->delta_limit;
} }
size = cur_entry->size;
oldsize = old_entry->size;
sizediff = oldsize > size ? oldsize - size : size - oldsize;
if (size < 50)
return -1;
if (old_entry->depth >= max_depth) if (old_entry->depth >= max_depth)
return 0; return 0;
@ -1048,9 +1042,12 @@ static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_de
* more space-efficient (deletes don't have to say _what_ they * more space-efficient (deletes don't have to say _what_ they
* delete). * delete).
*/ */
size = cur_entry->size;
max_size = size / 2 - 20; max_size = size / 2 - 20;
if (cur_entry->delta) if (cur_entry->delta)
max_size = cur_entry->delta_size-1; max_size = cur_entry->delta_size-1;
oldsize = old_entry->size;
sizediff = oldsize < size ? size - oldsize : 0;
if (sizediff >= max_size) if (sizediff >= max_size)
return 0; return 0;
delta_buf = diff_delta(old->data, oldsize, delta_buf = diff_delta(old->data, oldsize,
@ -1109,6 +1106,9 @@ static void find_deltas(struct object_entry **list, int window, int depth)
*/ */
continue; continue;
if (entry->size < 50)
continue;
free(n->data); free(n->data);
n->entry = entry; n->entry = entry;
n->data = read_sha1_file(entry->sha1, type, &size); n->data = read_sha1_file(entry->sha1, type, &size);
@ -1239,6 +1239,7 @@ int main(int argc, char **argv)
setup_git_directory(); setup_git_directory();
progress = isatty(2);
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
const char *arg = argv[i]; const char *arg = argv[i];
@ -1269,6 +1270,10 @@ int main(int argc, char **argv)
usage(pack_usage); usage(pack_usage);
continue; continue;
} }
if (!strcmp("--progress", arg)) {
progress = 1;
continue;
}
if (!strcmp("-q", arg)) { if (!strcmp("-q", arg)) {
progress = 0; progress = 0;
continue; continue;

View File

@ -14,7 +14,7 @@
#include "delta.h" #include "delta.h"
void *patch_delta(void *src_buf, unsigned long src_size, void *patch_delta(void *src_buf, unsigned long src_size,
void *delta_buf, unsigned long delta_size, const void *delta_buf, unsigned long delta_size,
unsigned long *dst_size) unsigned long *dst_size)
{ {
const unsigned char *data, *top; const unsigned char *data, *top;

4
refs.c
View File

@ -76,8 +76,8 @@ int create_symref(const char *git_HEAD, const char *refs_heads_master)
char ref[1000]; char ref[1000];
int fd, len, written; int fd, len, written;
#ifdef USE_SYMLINK_HEAD #ifndef NO_SYMLINK_HEAD
if (!only_use_symrefs) { if (prefer_symlink_refs) {
unlink(git_HEAD); unlink(git_HEAD);
if (!symlink(refs_heads_master, git_HEAD)) if (!symlink(refs_heads_master, git_HEAD))
return 0; return 0;

View File

@ -2,46 +2,63 @@
#include <regex.h> #include <regex.h>
static const char git_config_set_usage[] = static const char git_config_set_usage[] =
"git-repo-config [ --bool | --int ] [--get | --get-all | --replace-all | --unset | --unset-all] name [value [value_regex]]"; "git-repo-config [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --unset | --unset-all] name [value [value_regex]] | --list";
static char* key = NULL; static char* key = NULL;
static char* value = NULL; static regex_t* key_regexp = NULL;
static regex_t* regexp = NULL; static regex_t* regexp = NULL;
static int show_keys = 0;
static int use_key_regexp = 0;
static int do_all = 0; static int do_all = 0;
static int do_not_match = 0; static int do_not_match = 0;
static int seen = 0; static int seen = 0;
static enum { T_RAW, T_INT, T_BOOL } type = T_RAW; static enum { T_RAW, T_INT, T_BOOL } type = T_RAW;
static int show_all_config(const char *key_, const char *value_)
{
if (value_)
printf("%s=%s\n", key_, value_);
else
printf("%s\n", key_);
return 0;
}
static int show_config(const char* key_, const char* value_) static int show_config(const char* key_, const char* value_)
{ {
char value[256];
const char *vptr = value;
int dup_error = 0;
if (value_ == NULL) if (value_ == NULL)
value_ = ""; value_ = "";
if (!strcmp(key_, key) && if (!use_key_regexp && strcmp(key_, key))
(regexp == NULL || return 0;
(do_not_match ^ if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0))
!regexec(regexp, value_, 0, NULL, 0)))) { return 0;
if (do_all) { if (regexp != NULL &&
printf("%s\n", value_); (do_not_match ^
regexec(regexp, value_, 0, NULL, 0)))
return 0; return 0;
}
if (seen > 0) {
fprintf(stderr, "More than one value: %s\n", value);
free(value);
}
if (type == T_INT) { if (show_keys)
value = malloc(256); printf("%s ", key_);
if (seen && !do_all)
dup_error = 1;
if (type == T_INT)
sprintf(value, "%d", git_config_int(key_, value_)); sprintf(value, "%d", git_config_int(key_, value_));
} else if (type == T_BOOL) { else if (type == T_BOOL)
value = malloc(256); vptr = git_config_bool(key_, value_) ? "true" : "false";
sprintf(value, "%s", git_config_bool(key_, value_) else
? "true" : "false"); vptr = value_;
} else {
value = strdup(value_);
}
seen++; seen++;
if (dup_error) {
error("More than one value for the key %s: %s",
key_, vptr);
} }
else
printf("%s\n", vptr);
return 0; return 0;
} }
@ -54,6 +71,14 @@ static int get_value(const char* key_, const char* regex_)
key[i] = tolower(key_[i]); key[i] = tolower(key_[i]);
key[i] = 0; key[i] = 0;
if (use_key_regexp) {
key_regexp = (regex_t*)malloc(sizeof(regex_t));
if (regcomp(key_regexp, key, REG_EXTENDED)) {
fprintf(stderr, "Invalid key pattern: %s\n", key_);
return -1;
}
}
if (regex_) { if (regex_) {
if (regex_[0] == '!') { if (regex_[0] == '!') {
do_not_match = 1; do_not_match = 1;
@ -67,11 +92,7 @@ static int get_value(const char* key_, const char* regex_)
} }
} }
i = git_config(show_config); git_config(show_config);
if (value) {
printf("%s\n", value);
free(value);
}
free(key); free(key);
if (regexp) { if (regexp) {
regfree(regexp); regfree(regexp);
@ -79,9 +100,9 @@ static int get_value(const char* key_, const char* regex_)
} }
if (do_all) if (do_all)
return 0; return !seen;
return seen == 1 ? 0 : 1; return (seen == 1) ? 0 : 1;
} }
int main(int argc, const char **argv) int main(int argc, const char **argv)
@ -93,6 +114,8 @@ int main(int argc, const char **argv)
type = T_INT; type = T_INT;
else if (!strcmp(argv[1], "--bool")) else if (!strcmp(argv[1], "--bool"))
type = T_BOOL; type = T_BOOL;
else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l"))
return git_config(show_all_config);
else else
break; break;
argc--; argc--;
@ -112,6 +135,11 @@ int main(int argc, const char **argv)
else if (!strcmp(argv[1], "--get-all")) { else if (!strcmp(argv[1], "--get-all")) {
do_all = 1; do_all = 1;
return get_value(argv[2], NULL); return get_value(argv[2], NULL);
} else if (!strcmp(argv[1], "--get-regexp")) {
show_keys = 1;
use_key_regexp = 1;
do_all = 1;
return get_value(argv[2], NULL);
} else } else
return git_config_set(argv[1], argv[2]); return git_config_set(argv[1], argv[2]);
@ -125,6 +153,11 @@ int main(int argc, const char **argv)
else if (!strcmp(argv[1], "--get-all")) { else if (!strcmp(argv[1], "--get-all")) {
do_all = 1; do_all = 1;
return get_value(argv[2], argv[3]); return get_value(argv[2], argv[3]);
} else if (!strcmp(argv[1], "--get-regexp")) {
show_keys = 1;
use_key_regexp = 1;
do_all = 1;
return get_value(argv[2], argv[3]);
} else if (!strcmp(argv[1], "--replace-all")) } else if (!strcmp(argv[1], "--replace-all"))
return git_config_set_multivar(argv[2], argv[3], NULL, 1); return git_config_set_multivar(argv[2], argv[3], NULL, 1);

View File

@ -169,14 +169,12 @@ int main(int argc, char **argv)
git_config(git_default_config); git_config(git_default_config);
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
struct stat st;
char *arg = argv[i]; char *arg = argv[i];
char *dotdot; char *dotdot;
if (as_is) { if (as_is) {
if (show_file(arg) && as_is < 2) if (show_file(arg) && as_is < 2)
if (lstat(arg, &st) < 0) verify_filename(prefix, arg);
die("'%s': %s", arg, strerror(errno));
continue; continue;
} }
if (!strcmp(arg,"-n")) { if (!strcmp(arg,"-n")) {
@ -342,8 +340,7 @@ int main(int argc, char **argv)
continue; continue;
if (verify) if (verify)
die("Needed a single revision"); die("Needed a single revision");
if (lstat(arg, &st) < 0) verify_filename(prefix, arg);
die("'%s': %s", arg, strerror(errno));
} }
show_default(); show_default();
if (verify && revs_count != 1) if (verify && revs_count != 1)

View File

@ -477,6 +477,36 @@ static void handle_all(struct rev_info *revs, unsigned flags)
for_each_ref(handle_one_ref); for_each_ref(handle_one_ref);
} }
static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
{
unsigned char sha1[20];
struct object *it;
struct commit *commit;
struct commit_list *parents;
if (*arg == '^') {
flags ^= UNINTERESTING;
arg++;
}
if (get_sha1(arg, sha1))
return 0;
while (1) {
it = get_reference(revs, arg, sha1, 0);
if (strcmp(it->type, tag_type))
break;
memcpy(sha1, ((struct tag*)it)->tagged->sha1, 20);
}
if (strcmp(it->type, commit_type))
return 0;
commit = (struct commit *)it;
for (parents = commit->parents; parents; parents = parents->next) {
it = &parents->item->object;
it->flags |= flags;
add_pending_object(revs, it, arg);
}
return 1;
}
void init_revisions(struct rev_info *revs) void init_revisions(struct rev_info *revs)
{ {
memset(revs, 0, sizeof(*revs)); memset(revs, 0, sizeof(*revs));
@ -544,7 +574,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->max_count = atoi(arg + 12); revs->max_count = atoi(arg + 12);
continue; continue;
} }
/* accept -<digit>, like traditilnal "head" */ /* accept -<digit>, like traditional "head" */
if ((*arg == '-') && isdigit(arg[1])) { if ((*arg == '-') && isdigit(arg[1])) {
revs->max_count = atoi(arg + 1); revs->max_count = atoi(arg + 1);
continue; continue;
@ -664,6 +694,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
} }
if (!strcmp(arg, "-c")) { if (!strcmp(arg, "-c")) {
revs->diff = 1; revs->diff = 1;
revs->dense_combined_merges = 0;
revs->combine_merges = 1; revs->combine_merges = 1;
continue; continue;
} }
@ -740,32 +771,49 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
include = get_reference(revs, next, sha1, flags); include = get_reference(revs, next, sha1, flags);
if (!exclude || !include) if (!exclude || !include)
die("Invalid revision range %s..%s", arg, next); die("Invalid revision range %s..%s", arg, next);
if (!seen_dashdash) {
*dotdot = '.';
verify_non_filename(revs->prefix, arg);
}
add_pending_object(revs, exclude, this); add_pending_object(revs, exclude, this);
add_pending_object(revs, include, next); add_pending_object(revs, include, next);
continue; continue;
} }
*dotdot = '.'; *dotdot = '.';
} }
dotdot = strstr(arg, "^@");
if (dotdot && !dotdot[2]) {
*dotdot = 0;
if (add_parents_only(revs, arg, flags))
continue;
*dotdot = '^';
}
local_flags = 0; local_flags = 0;
if (*arg == '^') { if (*arg == '^') {
local_flags = UNINTERESTING; local_flags = UNINTERESTING;
arg++; arg++;
} }
if (get_sha1(arg, sha1) < 0) { if (get_sha1(arg, sha1) < 0) {
struct stat st;
int j; int j;
if (seen_dashdash || local_flags) if (seen_dashdash || local_flags)
die("bad revision '%s'", arg); die("bad revision '%s'", arg);
/* If we didn't have a "--", all filenames must exist */ /* If we didn't have a "--":
for (j = i; j < argc; j++) { * (1) all filenames must exist;
if (lstat(argv[j], &st) < 0) * (2) all rev-args must not be interpretable
die("'%s': %s", argv[j], strerror(errno)); * as a valid filename.
} * but the latter we have checked in the main loop.
*/
for (j = i; j < argc; j++)
verify_filename(revs->prefix, argv[j]);
revs->prune_data = get_pathspec(revs->prefix, argv + i); revs->prune_data = get_pathspec(revs->prefix, argv + i);
break; break;
} }
if (!seen_dashdash)
verify_non_filename(revs->prefix, arg);
object = get_reference(revs, arg, sha1, flags ^ local_flags); object = get_reference(revs, arg, sha1, flags ^ local_flags);
add_pending_object(revs, object, arg); add_pending_object(revs, object, arg);
} }
@ -789,7 +837,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
} }
if (revs->combine_merges) { if (revs->combine_merges) {
revs->ignore_merges = 0; revs->ignore_merges = 0;
if (revs->dense_combined_merges) if (revs->dense_combined_merges &&
(revs->diffopt.output_format != DIFF_FORMAT_DIFFSTAT))
revs->diffopt.output_format = DIFF_FORMAT_PATCH; revs->diffopt.output_format = DIFF_FORMAT_PATCH;
} }
revs->diffopt.abbrev = revs->abbrev; revs->diffopt.abbrev = revs->abbrev;

43
setup.c
View File

@ -62,6 +62,49 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
return path; return path;
} }
/*
* Verify a filename that we got as an argument for a pathspec
* entry. Note that a filename that begins with "-" never verifies
* as true, because even if such a filename were to exist, we want
* it to be preceded by the "--" marker (or we want the user to
* use a format like "./-filename")
*/
void verify_filename(const char *prefix, const char *arg)
{
const char *name;
struct stat st;
if (*arg == '-')
die("bad flag '%s' used after filename", arg);
name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
if (!lstat(name, &st))
return;
if (errno == ENOENT)
die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
"Use '--' to separate paths from revisions", arg);
die("'%s': %s", arg, strerror(errno));
}
/*
* Opposite of the above: the command line did not have -- marker
* and we parsed the arg as a refname. It should not be interpretable
* as a filename.
*/
void verify_non_filename(const char *prefix, const char *arg)
{
const char *name;
struct stat st;
if (*arg == '-')
return; /* flag */
name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
if (!lstat(name, &st))
die("ambiguous argument '%s': both revision and filename\n"
"Use '--' to separate filenames from revisions", arg);
if (errno != ENOENT)
die("'%s': %s", arg, strerror(errno));
}
const char **get_pathspec(const char *prefix, const char **pathspec) const char **get_pathspec(const char *prefix, const char **pathspec)
{ {
const char *entry = *pathspec; const char *entry = *pathspec;

View File

@ -108,9 +108,10 @@ int safe_create_leading_directories(char *path)
char * sha1_to_hex(const unsigned char *sha1) char * sha1_to_hex(const unsigned char *sha1)
{ {
static char buffer[50]; static int bufno;
static char hexbuffer[4][50];
static const char hex[] = "0123456789abcdef"; static const char hex[] = "0123456789abcdef";
char *buf = buffer; char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
int i; int i;
for (i = 0; i < 20; i++) { for (i = 0; i < 20; i++) {

View File

@ -5,7 +5,7 @@
#include "refs.h" #include "refs.h"
static const char show_branch_usage[] = static const char show_branch_usage[] =
"git-show-branch [--current] [--all] [--heads] [--tags] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...]"; "git-show-branch [--dense] [--current] [--all] [--heads] [--tags] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...]";
static int default_num = 0; static int default_num = 0;
static int default_alloc = 0; static int default_alloc = 0;
@ -527,6 +527,27 @@ static int git_show_branch_config(const char *var, const char *value)
return git_default_config(var, value); return git_default_config(var, value);
} }
static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
{
/* If the commit is tip of the named branches, do not
* omit it.
* Otherwise, if it is a merge that is reachable from only one
* tip, it is not that interesting.
*/
int i, flag, count;
for (i = 0; i < n; i++)
if (rev[i] == commit)
return 0;
flag = commit->object.flags;
for (i = count = 0; i < n; i++) {
if (flag & (1u << (i + REV_SHIFT)))
count++;
}
if (count == 1)
return 1;
return 0;
}
int main(int ac, char **av) int main(int ac, char **av)
{ {
struct commit *rev[MAX_REVS], *commit; struct commit *rev[MAX_REVS], *commit;
@ -548,6 +569,7 @@ int main(int ac, char **av)
int with_current_branch = 0; int with_current_branch = 0;
int head_at = -1; int head_at = -1;
int topics = 0; int topics = 0;
int dense = 1;
setup_git_directory(); setup_git_directory();
git_config(git_show_branch_config); git_config(git_show_branch_config);
@ -590,6 +612,8 @@ int main(int ac, char **av)
lifo = 1; lifo = 1;
else if (!strcmp(arg, "--topics")) else if (!strcmp(arg, "--topics"))
topics = 1; topics = 1;
else if (!strcmp(arg, "--sparse"))
dense = 0;
else if (!strcmp(arg, "--date-order")) else if (!strcmp(arg, "--date-order"))
lifo = 0; lifo = 0;
else else
@ -732,12 +756,15 @@ int main(int ac, char **av)
shown_merge_point |= is_merge_point; shown_merge_point |= is_merge_point;
if (1 < num_rev) { if (1 < num_rev) {
int is_merge = !!(commit->parents && commit->parents->next); int is_merge = !!(commit->parents &&
commit->parents->next);
if (topics && if (topics &&
!is_merge_point && !is_merge_point &&
(this_flag & (1u << REV_SHIFT))) (this_flag & (1u << REV_SHIFT)))
continue; continue;
if (dense && is_merge &&
omit_in_dense(commit, rev, num_rev))
continue;
for (i = 0; i < num_rev; i++) { for (i = 0; i < num_rev; i++) {
int mark; int mark;
if (!(this_flag & (1u << (i + REV_SHIFT)))) if (!(this_flag & (1u << (i + REV_SHIFT))))

View File

@ -174,6 +174,27 @@ test_expect_success \
'git-ls-tree -r output for a known tree.' \ 'git-ls-tree -r output for a known tree.' \
'diff current expected' 'diff current expected'
# But with -r -t we can have both.
test_expect_success \
'showing tree with git-ls-tree -r -t' \
'git-ls-tree -r -t $tree >current'
cat >expected <<\EOF
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2
100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2
120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym
040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3
100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3
120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym
040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3
100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3
120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym
EOF
test_expect_success \
'git-ls-tree -r output for a known tree.' \
'diff current expected'
################################################################ ################################################################
rm .git/index rm .git/index
test_expect_success \ test_expect_success \
@ -205,4 +226,32 @@ test_expect_success \
'no diff after checkout and git-update-index --refresh.' \ 'no diff after checkout and git-update-index --refresh.' \
'git-diff-files >current && cmp -s current /dev/null' 'git-diff-files >current && cmp -s current /dev/null'
################################################################
P=087704a96baf1c2d1c869a8b084481e121c88b5b
test_expect_success \
'git-commit-tree records the correct tree in a commit.' \
'commit0=$(echo NO | git-commit-tree $P) &&
tree=$(git show --pretty=raw $commit0 |
sed -n -e "s/^tree //p" -e "/^author /q") &&
test "z$tree" = "z$P"'
test_expect_success \
'git-commit-tree records the correct parent in a commit.' \
'commit1=$(echo NO | git-commit-tree $P -p $commit0) &&
parent=$(git show --pretty=raw $commit1 |
sed -n -e "s/^parent //p" -e "/^author /q") &&
test "z$commit0" = "z$parent"'
test_expect_success \
'git-commit-tree omits duplicated parent in a commit.' \
'commit2=$(echo NO | git-commit-tree $P -p $commit0 -p $commit0) &&
parent=$(git show --pretty=raw $commit2 |
sed -n -e "s/^parent //p" -e "/^author /q" |
sort -u) &&
test "z$commit0" = "z$parent" &&
numparent=$(git show --pretty=raw $commit2 |
sed -n -e "s/^parent //p" -e "/^author /q" |
wc -l) &&
test $numparent = 1'
test_done test_done

View File

@ -37,7 +37,7 @@ compare_change () {
} }
check_cache_at () { check_cache_at () {
clean_if_empty=`git-diff-files "$1"` clean_if_empty=`git-diff-files -- "$1"`
case "$clean_if_empty" in case "$clean_if_empty" in
'') echo "$1: clean" ;; '') echo "$1: clean" ;;
?*) echo "$1: dirty" ;; ?*) echo "$1: dirty" ;;

View File

@ -20,7 +20,7 @@ compare_change () {
} }
check_cache_at () { check_cache_at () {
clean_if_empty=`git-diff-files "$1"` clean_if_empty=`git-diff-files -- "$1"`
case "$clean_if_empty" in case "$clean_if_empty" in
'') echo "$1: clean" ;; '') echo "$1: clean" ;;
?*) echo "$1: dirty" ;; ?*) echo "$1: dirty" ;;

View File

@ -247,6 +247,24 @@ EOF
test_expect_success 'hierarchical section value' 'cmp .git/config expect' test_expect_success 'hierarchical section value' 'cmp .git/config expect'
cat > expect << EOF
beta.noindent=sillyValue
nextsection.nonewline=wow2 for me
123456.a123=987
1.2.3.alpha=beta
EOF
test_expect_success 'working --list' \
'git-repo-config --list > output && cmp output expect'
cat > expect << EOF
beta.noindent sillyValue
nextsection.nonewline wow2 for me
EOF
test_expect_success '--get-regexp' \
'git-repo-config --get-regexp in > output && cmp output expect'
cat > .git/config << EOF cat > .git/config << EOF
[novalue] [novalue]
variable variable
@ -255,5 +273,41 @@ EOF
test_expect_success 'get variable with no value' \ test_expect_success 'get variable with no value' \
'git-repo-config --get novalue.variable ^$' 'git-repo-config --get novalue.variable ^$'
git-repo-config > output 2>&1
test_expect_success 'no arguments, but no crash' \
"test $? = 129 && grep usage output"
cat > .git/config << EOF
[a.b]
c = d
EOF
git-repo-config a.x y
cat > expect << EOF
[a.b]
c = d
[a]
x = y
EOF
test_expect_success 'new section is partial match of another' 'cmp .git/config expect'
git-repo-config b.x y
git-repo-config a.b c
cat > expect << EOF
[a.b]
c = d
[a]
x = y
b = c
[b]
x = y
EOF
test_expect_success 'new variable inserts into proper section' 'cmp .git/config expect'
test_done test_done

View File

@ -28,7 +28,7 @@ cat >expected <<\EOF
EOF EOF
test_expect_success \ test_expect_success \
'limit to path should show nothing' \ 'limit to path should show nothing' \
'git-diff-index --cached $tree path >current && 'git-diff-index --cached $tree -- path >current &&
compare_diff_raw current expected' compare_diff_raw current expected'
cat >expected <<\EOF cat >expected <<\EOF
@ -36,7 +36,7 @@ cat >expected <<\EOF
EOF EOF
test_expect_success \ test_expect_success \
'limit to path1 should show path1/file1' \ 'limit to path1 should show path1/file1' \
'git-diff-index --cached $tree path1 >current && 'git-diff-index --cached $tree -- path1 >current &&
compare_diff_raw current expected' compare_diff_raw current expected'
cat >expected <<\EOF cat >expected <<\EOF
@ -44,7 +44,7 @@ cat >expected <<\EOF
EOF EOF
test_expect_success \ test_expect_success \
'limit to path1/ should show path1/file1' \ 'limit to path1/ should show path1/file1' \
'git-diff-index --cached $tree path1/ >current && 'git-diff-index --cached $tree -- path1/ >current &&
compare_diff_raw current expected' compare_diff_raw current expected'
cat >expected <<\EOF cat >expected <<\EOF
@ -52,14 +52,14 @@ cat >expected <<\EOF
EOF EOF
test_expect_success \ test_expect_success \
'limit to file0 should show file0' \ 'limit to file0 should show file0' \
'git-diff-index --cached $tree file0 >current && 'git-diff-index --cached $tree -- file0 >current &&
compare_diff_raw current expected' compare_diff_raw current expected'
cat >expected <<\EOF cat >expected <<\EOF
EOF EOF
test_expect_success \ test_expect_success \
'limit to file0/ should emit nothing.' \ 'limit to file0/ should emit nothing.' \
'git-diff-index --cached $tree file0/ >current && 'git-diff-index --cached $tree -- file0/ >current &&
compare_diff_raw current expected' compare_diff_raw current expected'
test_done test_done

View File

@ -6,6 +6,7 @@
#include "cache.h" #include "cache.h"
#include "strbuf.h" #include "strbuf.h"
#include "quote.h" #include "quote.h"
#include "tree-walk.h"
/* /*
* Default to not allowing changes to the list of files. The * Default to not allowing changes to the list of files. The
@ -328,7 +329,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
return 0; return 0;
} }
static int chmod_path(int flip, const char *path) static void chmod_path(int flip, const char *path)
{ {
int pos; int pos;
struct cache_entry *ce; struct cache_entry *ce;
@ -336,21 +337,24 @@ static int chmod_path(int flip, const char *path)
pos = cache_name_pos(path, strlen(path)); pos = cache_name_pos(path, strlen(path));
if (pos < 0) if (pos < 0)
return -1; goto fail;
ce = active_cache[pos]; ce = active_cache[pos];
mode = ntohl(ce->ce_mode); mode = ntohl(ce->ce_mode);
if (!S_ISREG(mode)) if (!S_ISREG(mode))
return -1; goto fail;
switch (flip) { switch (flip) {
case '+': case '+':
ce->ce_mode |= htonl(0111); break; ce->ce_mode |= htonl(0111); break;
case '-': case '-':
ce->ce_mode &= htonl(~0111); break; ce->ce_mode &= htonl(~0111); break;
default: default:
return -1; goto fail;
} }
active_cache_changed = 1; active_cache_changed = 1;
return 0; report("chmod %cx '%s'", flip, path);
return;
fail:
die("git-update-index: cannot chmod %cx '%s'", flip, path);
} }
static struct cache_file cache_file; static struct cache_file cache_file;
@ -360,23 +364,26 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
const char *p = prefix_path(prefix, prefix_length, path); const char *p = prefix_path(prefix, prefix_length, path);
if (!verify_path(p)) { if (!verify_path(p)) {
fprintf(stderr, "Ignoring path %s\n", path); fprintf(stderr, "Ignoring path %s\n", path);
return; goto free_return;
} }
if (mark_valid_only) { if (mark_valid_only) {
if (mark_valid(p)) if (mark_valid(p))
die("Unable to mark file %s", path); die("Unable to mark file %s", path);
return; goto free_return;
} }
if (force_remove) { if (force_remove) {
if (remove_file_from_cache(p)) if (remove_file_from_cache(p))
die("git-update-index: unable to remove %s", path); die("git-update-index: unable to remove %s", path);
report("remove '%s'", path); report("remove '%s'", path);
return; goto free_return;
} }
if (add_file_to_cache(p)) if (add_file_to_cache(p))
die("Unable to process file %s", path); die("Unable to process file %s", path);
report("add '%s'", path); report("add '%s'", path);
free_return:
if (p != path)
free((char*)p);
} }
static void read_index_info(int line_termination) static void read_index_info(int line_termination)
@ -469,7 +476,129 @@ static void read_index_info(int line_termination)
} }
static const char update_index_usage[] = static const char update_index_usage[] =
"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--cacheinfo] [--chmod=(+|-)x] [--info-only] [--force-remove] [--stdin] [--index-info] [--ignore-missing] [-z] [--verbose] [--] <file>..."; "git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--ignore-missing] [-z] [--verbose] [--] <file>...";
static unsigned char head_sha1[20];
static unsigned char merge_head_sha1[20];
static struct cache_entry *read_one_ent(const char *which,
unsigned char *ent, const char *path,
int namelen, int stage)
{
unsigned mode;
unsigned char sha1[20];
int size;
struct cache_entry *ce;
if (get_tree_entry(ent, path, sha1, &mode)) {
error("%s: not in %s branch.", path, which);
return NULL;
}
if (mode == S_IFDIR) {
error("%s: not a blob in %s branch.", path, which);
return NULL;
}
size = cache_entry_size(namelen);
ce = xcalloc(1, size);
memcpy(ce->sha1, sha1, 20);
memcpy(ce->name, path, namelen);
ce->ce_flags = create_ce_flags(namelen, stage);
ce->ce_mode = create_ce_mode(mode);
return ce;
}
static int unresolve_one(const char *path)
{
int namelen = strlen(path);
int pos;
int ret = 0;
struct cache_entry *ce_2 = NULL, *ce_3 = NULL;
/* See if there is such entry in the index. */
pos = cache_name_pos(path, namelen);
if (pos < 0) {
/* If there isn't, either it is unmerged, or
* resolved as "removed" by mistake. We do not
* want to do anything in the former case.
*/
pos = -pos-1;
if (pos < active_nr) {
struct cache_entry *ce = active_cache[pos];
if (ce_namelen(ce) == namelen &&
!memcmp(ce->name, path, namelen)) {
fprintf(stderr,
"%s: skipping still unmerged path.\n",
path);
goto free_return;
}
}
}
/* Grab blobs from given path from HEAD and MERGE_HEAD,
* stuff HEAD version in stage #2,
* stuff MERGE_HEAD version in stage #3.
*/
ce_2 = read_one_ent("our", head_sha1, path, namelen, 2);
ce_3 = read_one_ent("their", merge_head_sha1, path, namelen, 3);
if (!ce_2 || !ce_3) {
ret = -1;
goto free_return;
}
if (!memcmp(ce_2->sha1, ce_3->sha1, 20) &&
ce_2->ce_mode == ce_3->ce_mode) {
fprintf(stderr, "%s: identical in both, skipping.\n",
path);
goto free_return;
}
remove_file_from_cache(path);
if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) {
error("%s: cannot add our version to the index.", path);
ret = -1;
goto free_return;
}
if (!add_cache_entry(ce_3, ADD_CACHE_OK_TO_ADD))
return 0;
error("%s: cannot add their version to the index.", path);
ret = -1;
free_return:
free(ce_2);
free(ce_3);
return ret;
}
static void read_head_pointers(void)
{
if (read_ref(git_path("HEAD"), head_sha1))
die("No HEAD -- no initial commit yet?\n");
if (read_ref(git_path("MERGE_HEAD"), merge_head_sha1)) {
fprintf(stderr, "Not in the middle of a merge.\n");
exit(0);
}
}
static int do_unresolve(int ac, const char **av,
const char *prefix, int prefix_length)
{
int i;
int err = 0;
/* Read HEAD and MERGE_HEAD; if MERGE_HEAD does not exist, we
* are not doing a merge, so exit with success status.
*/
read_head_pointers();
for (i = 1; i < ac; i++) {
const char *arg = av[i];
const char *p = prefix_path(prefix, prefix_length, arg);
err |= unresolve_one(p);
if (p != arg)
free((char*)p);
}
return err;
}
int main(int argc, const char **argv) int main(int argc, const char **argv)
{ {
@ -478,6 +607,7 @@ int main(int argc, const char **argv)
int read_from_stdin = 0; int read_from_stdin = 0;
const char *prefix = setup_git_directory(); const char *prefix = setup_git_directory();
int prefix_length = prefix ? strlen(prefix) : 0; int prefix_length = prefix ? strlen(prefix) : 0;
char set_executable_bit = 0;
git_config(git_default_config); git_config(git_default_config);
@ -544,8 +674,7 @@ int main(int argc, const char **argv)
!strcmp(path, "--chmod=+x")) { !strcmp(path, "--chmod=+x")) {
if (argc <= i+1) if (argc <= i+1)
die("git-update-index: %s <path>", path); die("git-update-index: %s <path>", path);
if (chmod_path(path[8], argv[++i])) set_executable_bit = path[8];
die("git-update-index: %s cannot chmod %s", path, argv[i]);
continue; continue;
} }
if (!strcmp(path, "--assume-unchanged")) { if (!strcmp(path, "--assume-unchanged")) {
@ -581,6 +710,13 @@ int main(int argc, const char **argv)
read_index_info(line_termination); read_index_info(line_termination);
break; break;
} }
if (!strcmp(path, "--unresolve")) {
has_errors = do_unresolve(argc - i, argv + i,
prefix, prefix_length);
if (has_errors)
active_cache_changed = 0;
goto finish;
}
if (!strcmp(path, "--ignore-missing")) { if (!strcmp(path, "--ignore-missing")) {
not_new = 1; not_new = 1;
continue; continue;
@ -594,12 +730,15 @@ int main(int argc, const char **argv)
die("unknown option %s", path); die("unknown option %s", path);
} }
update_one(path, prefix, prefix_length); update_one(path, prefix, prefix_length);
if (set_executable_bit)
chmod_path(set_executable_bit, path);
} }
if (read_from_stdin) { if (read_from_stdin) {
struct strbuf buf; struct strbuf buf;
strbuf_init(&buf); strbuf_init(&buf);
while (1) { while (1) {
char *path_name; char *path_name;
const char *p;
read_line(&buf, stdin, line_termination); read_line(&buf, stdin, line_termination);
if (buf.eof) if (buf.eof)
break; break;
@ -607,11 +746,18 @@ int main(int argc, const char **argv)
path_name = unquote_c_style(buf.buf, NULL); path_name = unquote_c_style(buf.buf, NULL);
else else
path_name = buf.buf; path_name = buf.buf;
update_one(path_name, prefix, prefix_length); p = prefix_path(prefix, prefix_length, path_name);
update_one(p, NULL, 0);
if (set_executable_bit)
chmod_path(set_executable_bit, p);
if (p != path_name)
free((char*) p);
if (path_name != buf.buf) if (path_name != buf.buf)
free(path_name); free(path_name);
} }
} }
finish:
if (active_cache_changed) { if (active_cache_changed) {
if (write_cache(newfd, active_cache, active_nr) || if (write_cache(newfd, active_cache, active_nr) ||
commit_index_file(&cache_file)) commit_index_file(&cache_file))