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. ...maint
						commit
						c66b6c067e
					
				|  | @ -79,7 +79,7 @@ clean: | |||
| 	asciidoc -b xhtml11 -d manpage -f asciidoc.conf $< | ||||
|  | ||||
| %.1 %.7 : %.xml | ||||
| 	xmlto man $< | ||||
| 	xmlto -m callouts.xsl man $< | ||||
|  | ||||
| %.xml : %.txt | ||||
| 	asciidoc -b docbook -d manpage -f asciidoc.conf $< | ||||
|  |  | |||
|  | @ -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
</xsl:text> | ||||
| 	<xsl:apply-templates/> | ||||
| 	<xsl:text>
</xsl:text> | ||||
| </xsl:template> | ||||
| <xsl:template match="callout"> | ||||
| 	<xsl:value-of select="concat('\fB',substring-after(@arearefs,'-'),'. \fR')"/> | ||||
| 	<xsl:apply-templates/> | ||||
| 	<xsl:text>.br
</xsl:text> | ||||
| </xsl:template> | ||||
| </xsl:stylesheet> | ||||
|  | @ -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]. | ||||
|  | @ -61,7 +61,8 @@ $ git prune | |||
| $ git count-objects <2> | ||||
| $ git repack <3> | ||||
| $ git prune <4> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> running without "--full" is usually cheap and assures the | ||||
| repository health reasonably well. | ||||
| <2> check how many loose objects there are and how much | ||||
|  | @ -69,17 +70,16 @@ diskspace is wasted by not repacking. | |||
| <3> without "-a" repacks incrementally.  repacking every 4-5MB | ||||
| of loose objects accumulation may be a good rule of thumb. | ||||
| <4> after repack, prune removes the duplicate loose objects. | ||||
| ------------ | ||||
|  | ||||
| Repack a small project into single pack.:: | ||||
| + | ||||
| ------------ | ||||
| $ git repack -a -d <1> | ||||
| $ git prune | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> pack all the objects reachable from the refs into one pack | ||||
| and remove unneeded other packs | ||||
| ------------ | ||||
|  | ||||
|  | ||||
| Individual Developer (Standalone)[[Individual Developer (Standalone)]] | ||||
|  | @ -129,10 +129,10 @@ $ git-init-db | |||
| $ git add . <1> | ||||
| $ git commit -m 'import of frotz source tree.' | ||||
| $ git tag v2.43 <2> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> add everything under the current directory. | ||||
| <2> make a lightweight, unannotated tag. | ||||
| ------------ | ||||
|  | ||||
| Create a topic branch and develop.:: | ||||
| + | ||||
|  | @ -153,7 +153,8 @@ $ git checkout master <9> | |||
| $ git pull . alsa-audio <10> | ||||
| $ git log --since='3 days ago' <11> | ||||
| $ git log v2.43.. curses/ <12> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> create a new topic branch. | ||||
| <2> revert your botched changes in "curses/ux_audio_oss.c". | ||||
| <3> you need to tell git if you added a new file; removal and | ||||
|  | @ -170,7 +171,6 @@ you originally wrote. | |||
| combined and include --max-count=10 (show 10 commits), --until='2005-12-10'. | ||||
| <12> view only the changes that touch what's in curses/ | ||||
| directory, since v2.43 tag. | ||||
| ------------ | ||||
|  | ||||
|  | ||||
| Individual Developer (Participant)[[Individual Developer (Participant)]] | ||||
|  | @ -208,7 +208,8 @@ $ git pull git://git.kernel.org/pub/.../jgarzik/libata-dev.git ALL <5> | |||
| $ git reset --hard ORIG_HEAD <6> | ||||
| $ git prune <7> | ||||
| $ git fetch --tags <8> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> repeat as needed. | ||||
| <2> extract patches from your branch for e-mail submission. | ||||
| <3> "pull" fetches from "origin" by default and merges into the | ||||
|  | @ -221,7 +222,6 @@ area we are interested in. | |||
| <7> garbage collect leftover objects from reverted pull. | ||||
| <8> from time to time, obtain official tags from the "origin" | ||||
| and store them under .git/refs/tags/. | ||||
| ------------ | ||||
|  | ||||
|  | ||||
| Push into another repository.:: | ||||
|  | @ -239,7 +239,8 @@ satellite$ git push origin <4> | |||
| mothership$ cd frotz | ||||
| mothership$ git checkout master | ||||
| mothership$ git pull . satellite <5> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> mothership machine has a frotz repository under your home | ||||
| directory; clone from it to start a repository on the satellite | ||||
| machine. | ||||
|  | @ -252,7 +253,6 @@ to local "origin" branch. | |||
| mothership machine.  You could use this as a back-up method. | ||||
| <5> on mothership machine, merge the work done on the satellite | ||||
| machine into the master branch. | ||||
| ------------ | ||||
|  | ||||
| Branch off of a specific tag.:: | ||||
| + | ||||
|  | @ -262,12 +262,12 @@ $ edit/compile/test; git commit -a | |||
| $ git checkout master | ||||
| $ git format-patch -k -m --stdout v2.6.14..private2.6.14 | | ||||
|   git am -3 -k <2> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> create a private branch based on a well known (but somewhat behind) | ||||
| tag. | ||||
| <2> forward port all changes in private2.6.14 branch to master branch | ||||
| without a formal "merging". | ||||
| ------------ | ||||
|  | ||||
|  | ||||
| Integrator[[Integrator]] | ||||
|  | @ -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 push ko <12> | ||||
| $ git push ko v0.99.9x <13> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> see what I was in the middle of doing, if any. | ||||
| <2> see what topic branches I have and think about how ready | ||||
| they are. | ||||
|  | @ -346,7 +347,6 @@ In the output from "git show-branch", "master" should have | |||
| everything "ko-master" has. | ||||
| <12> push out the bleeding edge. | ||||
| <13> push the tag out, too. | ||||
| ------------ | ||||
|  | ||||
|  | ||||
| Repository Administration[[Repository Administration]] | ||||
|  | @ -367,7 +367,6 @@ example of managing a shared central repository. | |||
|  | ||||
| Examples | ||||
| ~~~~~~~~ | ||||
|  | ||||
| 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 | ||||
| $ grep git /etc/shells <2> | ||||
| /usr/bin/git-shell | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> log-in shell is set to /usr/bin/git-shell, which does not | ||||
| allow anything but "git push" and "git pull".  The users should | ||||
| get an ssh access to the machine. | ||||
| <2> in many distributions /etc/shells needs to list what is used | ||||
| as the login shell. | ||||
| ------------ | ||||
|  | ||||
| CVS-style shared repository.:: | ||||
| + | ||||
|  | @ -419,7 +418,8 @@ $ cat info/allowed-users <4> | |||
| refs/heads/master	alice\|cindy | ||||
| refs/heads/doc-update	bob | ||||
| refs/tags/v[0-9]*	david | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> place the developers into the same git group. | ||||
| <2> and make the shared repository writable by the group. | ||||
| <3> use update-hook example by Carl from Documentation/howto/ | ||||
|  | @ -427,7 +427,6 @@ for branch policy control. | |||
| <4> alice and cindy can push into master, only bob can push into doc-update. | ||||
| david is the release manager and is the only person who can | ||||
| create and push version tags. | ||||
| ------------ | ||||
|  | ||||
| HTTP server to support dumb protocol transfer.:: | ||||
| + | ||||
|  | @ -435,7 +434,7 @@ HTTP server to support dumb protocol transfer.:: | |||
| dev$ git update-server-info <1> | ||||
| dev$ ftp user@isp.example.com <2> | ||||
| ftp> cp -r .git /home/user/myproject.git | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> make sure your info/refs and objects/info/packs are up-to-date | ||||
| <2> upload to public HTTP server hosted by your ISP. | ||||
| ------------ | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ OPTIONS | |||
| -v:: | ||||
|         Be verbose. | ||||
|  | ||||
| --:: | ||||
| \--:: | ||||
| 	This option can be used to separate command-line options from | ||||
| 	the list of files, (useful when filenames might be mistaken | ||||
| 	for command-line options). | ||||
|  |  | |||
|  | @ -3,22 +3,27 @@ git-branch(1) | |||
|  | ||||
| NAME | ||||
| ---- | ||||
| git-branch - Create a new branch, or remove an old one | ||||
| git-branch - List, create, or delete branches. | ||||
|  | ||||
| SYNOPSIS | ||||
| -------- | ||||
| [verse] | ||||
| 'git-branch' [[-f] <branchname> [<start-point>]] | ||||
| 'git-branch' (-d | -D) <branchname> | ||||
| 'git-branch' [-r] | ||||
| 'git-branch' [-f] <branchname> [<start-point>] | ||||
| 'git-branch' (-d | -D) <branchname>... | ||||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
| If no argument is provided, show available branches and mark current | ||||
| branch with star. Otherwise, create a new branch of name <branchname>. | ||||
| 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 no arguments given (or just `-r`) a list of available branches | ||||
| will be shown, the current branch will be highlighted with an asterisk. | ||||
|  | ||||
| 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 | ||||
|  | @ -30,18 +35,24 @@ OPTIONS | |||
| 	Delete a branch irrespective of its index status. | ||||
|  | ||||
| -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>:: | ||||
| 	The name of the branch to create or delete. | ||||
|  | ||||
| <start-point>:: | ||||
| 	Where to create the branch; defaults to HEAD. This | ||||
| 	option has no meaning with -d and -D. | ||||
| 	The new branch will be created with a HEAD equal to this.  It may | ||||
| 	be given as a branch name, a commit-id, or a tag.  If this option | ||||
| 	is omitted, the current branch is assumed. | ||||
|  | ||||
|  | ||||
|  | ||||
| Examples | ||||
| ~~~~~~~~ | ||||
| -------- | ||||
|  | ||||
| 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 | ||||
| $ git branch my2.6.14 v2.6.14   <1> | ||||
| $ git checkout my2.6.14 | ||||
|  | ||||
| <1> These two steps are the same as "checkout -b my2.6.14 v2.6.14". | ||||
| ------------ | ||||
| + | ||||
| <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:: | ||||
| + | ||||
|  | @ -60,10 +72,19 @@ Delete unneeded branch:: | |||
| $ git clone git://git.kernel.org/.../git.git my.git | ||||
| $ cd my.git | ||||
| $ git branch -D todo    <1> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> delete todo branch even if the "master" branch does not have all | ||||
| commits from todo branch. | ||||
| ------------ | ||||
|  | ||||
|  | ||||
| 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 | ||||
| ------ | ||||
|  |  | |||
|  | @ -63,7 +63,7 @@ OPTIONS | |||
| 	Only meaningful with `--stdin`; paths are separated with | ||||
| 	NUL character instead of LF. | ||||
|  | ||||
| --:: | ||||
| \--:: | ||||
| 	Do not interpret any more arguments as options. | ||||
|  | ||||
| The order of the flags used to matter, but not anymore. | ||||
|  |  | |||
|  | @ -70,15 +70,15 @@ $ git checkout master <1> | |||
| $ git checkout master~2 Makefile  <2> | ||||
| $ rm -f hello.c | ||||
| $ git checkout hello.c            <3> | ||||
|  | ||||
| <1> switch branch | ||||
| <2> take out a file out of other commit | ||||
| <3> or "git checkout -- hello.c", as in the next example. | ||||
| ------------ | ||||
| + | ||||
| If you have an unfortunate branch that is named `hello.c`, the | ||||
| last step above would be confused as an instruction to switch to | ||||
| that branch.  You should instead write: | ||||
| <1> switch branch | ||||
| <2> take out a file out of other commit | ||||
| <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 | ||||
|  |  | |||
|  | @ -11,11 +11,20 @@ SYNOPSIS | |||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
| Each commit between the fork-point and <head> is examined, and compared against | ||||
| the change each commit between the fork-point and <upstream> introduces. | ||||
| Commits already included in upstream are prefixed with '-' (meaning "drop from | ||||
| my local pull"), while commits missing from upstream are prefixed with '+' | ||||
| (meaning "add to the updated upstream"). | ||||
| The changeset (or "diff") of each commit between the fork-point and <head> | ||||
| is compared against each commit between the fork-point and <upstream>. | ||||
|  | ||||
| Every commit with a changeset that doesn't exist in the other branch | ||||
| 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 | ||||
| ------- | ||||
|  |  | |||
|  | @ -101,7 +101,7 @@ OPTIONS | |||
| 	is not allowed. | ||||
|  | ||||
| Examples | ||||
| ~~~~~~~~ | ||||
| -------- | ||||
|  | ||||
| Clone from upstream:: | ||||
| + | ||||
|  |  | |||
|  | @ -106,7 +106,7 @@ but can be used to amend a merge commit. | |||
| 	index and the latest commit does not match on the | ||||
| 	specified paths to avoid confusion. | ||||
|  | ||||
| --:: | ||||
| \--:: | ||||
| 	Do not interpret any more arguments as options. | ||||
|  | ||||
| <file>...:: | ||||
|  |  | |||
|  | @ -7,13 +7,23 @@ git-count-objects - Reports on unpacked objects | |||
|  | ||||
| SYNOPSIS | ||||
| -------- | ||||
| 'git-count-objects' | ||||
| 'git-count-objects' [-v] | ||||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
| 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. | ||||
|  | ||||
|  | ||||
| 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 | ||||
| ------ | ||||
| Written by Junio C Hamano <junkio@cox.net> | ||||
|  |  | |||
|  | @ -92,7 +92,7 @@ separated with a single space are given. | |||
| 	Furthermore, it lists only files which were modified | ||||
| 	from all parents. | ||||
|  | ||||
| -cc:: | ||||
| --cc:: | ||||
| 	This flag changes the way a merge commit patch is displayed, | ||||
| 	in a similar way to the '-c' option. It implies the '-c' | ||||
| 	and '-p' options and further compresses the patch output | ||||
|  |  | |||
|  | @ -49,13 +49,13 @@ Various ways to check your working tree:: | |||
| $ git diff            <1> | ||||
| $ git diff --cached   <2> | ||||
| $ git diff HEAD       <3> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> changes in the working tree since your last git-update-index. | ||||
| <2> changes between the index and your last commit; what you | ||||
| would be committing if you run "git commit" without "-a" option. | ||||
| <3> changes in the working tree since your last commit; what you | ||||
| would be committing if you run "git commit -a" | ||||
| ------------ | ||||
|  | ||||
| Comparing with arbitrary commits:: | ||||
| + | ||||
|  | @ -63,14 +63,14 @@ Comparing with arbitrary commits:: | |||
| $ git diff test            <1> | ||||
| $ git diff HEAD -- ./test  <2> | ||||
| $ git diff HEAD^ HEAD      <3> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> instead of using the tip of the current branch, compare with the | ||||
| tip of "test" branch. | ||||
| <2> instead of comparing with the tip of "test" branch, compare with | ||||
| the tip of the current branch, but limit the comparison to the | ||||
| file "test". | ||||
| <3> compare the version before the last commit and the last commit. | ||||
| ------------ | ||||
|  | ||||
|  | ||||
| Limiting the diff output:: | ||||
|  | @ -79,7 +79,8 @@ Limiting the diff output:: | |||
| $ git diff --diff-filter=MRC            <1> | ||||
| $ git diff --name-status -r             <2> | ||||
| $ git diff arch/i386 include/asm-i386   <3> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> show only modification, rename and copy, but not addition | ||||
| nor deletion. | ||||
| <2> show only names and the nature of change, but not actual | ||||
|  | @ -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 | ||||
| file in a subdirectory. | ||||
| <3> limit diff output to named subtrees. | ||||
| ------------ | ||||
|  | ||||
| Munging the diff output:: | ||||
| + | ||||
| ------------ | ||||
| $ git diff --find-copies-harder -B -C  <1> | ||||
| $ git diff -R                          <2> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> spend extra cycles to find renames, copies and complete | ||||
| rewrites (very expensive). | ||||
| <2> output diff in reverse. | ||||
| ------------ | ||||
|  | ||||
|  | ||||
| Author | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ CONFIGURATION | |||
| git-imap-send requires the following values in the repository | ||||
| configuration file (shown with examples): | ||||
|  | ||||
| .......................... | ||||
| [imap] | ||||
|     Folder = "INBOX.Drafts" | ||||
|  | ||||
|  | @ -38,8 +39,9 @@ configuration file (shown with examples): | |||
| [imap] | ||||
|     Host = imap.server.com | ||||
|     User = bob | ||||
|     Password = pwd | ||||
|     Pass = pwd | ||||
|     Port = 143 | ||||
| .......................... | ||||
|  | ||||
|  | ||||
| BUGS | ||||
|  |  | |||
|  | @ -62,10 +62,10 @@ Start a new git repository for an existing code base:: | |||
| $ cd /path/to/my/codebase | ||||
| $ git-init-db   <1> | ||||
| $ git-add .     <2> | ||||
|  | ||||
| ---------------- | ||||
| + | ||||
| <1> prepare /path/to/my/codebase/.git directory | ||||
| <2> add all existing file to the index | ||||
| ---------------- | ||||
|  | ||||
|  | ||||
| Author | ||||
|  |  | |||
|  | @ -14,13 +14,12 @@ DESCRIPTION | |||
| ----------- | ||||
| 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 | ||||
| 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. | ||||
|  | ||||
| This manual page describes only the most frequently used | ||||
| options. | ||||
| This manual page describes only the most frequently used 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 | ||||
| 	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'. | ||||
| 	The "--" is necessary to avoid confusion with the *branch* named | ||||
|  |  | |||
|  | @ -106,7 +106,7 @@ OPTIONS | |||
| 	lines, show only handful hexdigits prefix. | ||||
| 	Non default number of digits can be specified with --abbrev=<n>. | ||||
|  | ||||
| --:: | ||||
| \--:: | ||||
| 	Do not interpret any more arguments as options. | ||||
|  | ||||
| <file>:: | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ git-merge-index - Runs a merge for files needing merging | |||
|  | ||||
| SYNOPSIS | ||||
| -------- | ||||
| 'git-merge-index' [-o] [-q] <merge-program> (-a | -- | <file>\*) | ||||
| 'git-merge-index' [-o] [-q] <merge-program> (-a | \-- | <file>\*) | ||||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
|  | @ -19,7 +19,7 @@ files are passed as arguments 5, 6 and 7. | |||
|  | ||||
| OPTIONS | ||||
| ------- | ||||
| --:: | ||||
| \--:: | ||||
| 	Do not interpret any more arguments as options. | ||||
|  | ||||
| -a:: | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ Enter git-name-rev: | |||
|  | ||||
| ------------ | ||||
| % 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. | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ OPTIONS | |||
| 	Do not remove anything; just report what it would | ||||
| 	remove. | ||||
|  | ||||
| --:: | ||||
| \--:: | ||||
| 	Do not interpret any more arguments as options. | ||||
|  | ||||
| <head>...:: | ||||
|  |  | |||
|  | @ -3,38 +3,54 @@ git-rebase(1) | |||
|  | ||||
| NAME | ||||
| ---- | ||||
| git-rebase - Rebase local commits to new upstream head | ||||
| git-rebase - Rebase local commits to a new head | ||||
|  | ||||
| SYNOPSIS | ||||
| -------- | ||||
| 'git-rebase' [--onto <newbase>] <upstream> [<branch>] | ||||
|  | ||||
| 'git-rebase' --continue | ||||
|  | ||||
| 'git-rebase' --abort | ||||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
| git-rebase applies to <upstream> (or optionally to <newbase>) commits | ||||
| from <branch> that do not appear in <upstream>. When <branch> is not | ||||
| specified it defaults to the current branch (HEAD). | ||||
| git-rebase replaces <branch> with a new branch of the same name.  When | ||||
| the --onto option is provided the new branch starts 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 | ||||
| newly created line of commit objects, so the previous line will not be | ||||
| accessible unless there are other references to it already. | ||||
| It is possible that a merge failure will prevent this process from being | ||||
| completely automatic.  You will have to resolve any such merge failure | ||||
| 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": | ||||
|  | ||||
| ------------ | ||||
|           A---B---C topic | ||||
|          / | ||||
|     D---E---F---G master | ||||
| ------------ | ||||
|  | ||||
| From this point, the result of either of the following commands: | ||||
|  | ||||
|  | ||||
|     git-rebase master | ||||
|     git-rebase master topic | ||||
|  | ||||
| would be: | ||||
|  | ||||
| ------------ | ||||
|                   A'--B'--C' topic | ||||
|                  / | ||||
|     D---E---F---G master | ||||
| ------------ | ||||
|  | ||||
| While, starting from the same point, the result of either of the following | ||||
| commands: | ||||
|  | @ -44,21 +60,33 @@ commands: | |||
|  | ||||
| would be: | ||||
|  | ||||
| ------------ | ||||
|               A'--B'--C' topic | ||||
|              / | ||||
|     D---E---F---G master | ||||
| ------------ | ||||
|  | ||||
| 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 updating the index with the desired resolution, you can continue the | ||||
| rebasing process with | ||||
| and leave conflict markers in the tree.  You can use git diff to locate | ||||
| the markers (<<<<<<) and make edits to resolve the conflict.  For each | ||||
| 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 | ||||
|  | ||||
|     git reset --hard ORIG_HEAD | ||||
|     rm -r .dotest | ||||
|  | ||||
|     git rebase --abort | ||||
|  | ||||
| OPTIONS | ||||
| ------- | ||||
|  | @ -73,6 +101,28 @@ OPTIONS | |||
| <branch>:: | ||||
| 	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 | ||||
| ------ | ||||
| Written by Junio C Hamano <junkio@cox.net> | ||||
|  |  | |||
|  | @ -38,6 +38,7 @@ OPTIONS | |||
| -d:: | ||||
| 	After packing, if the newly created packs make some | ||||
| 	existing packs redundant, remove the redundant packs. | ||||
| 	Also runs gitlink:git-prune-packed[1]. | ||||
|  | ||||
| -l:: | ||||
|         Pass the `--local` option to `git pack-objects`, see | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ SYNOPSIS | |||
| 'git-repo-config' [type] --get-all name [value_regex] | ||||
| 'git-repo-config' [type] --unset name [value_regex] | ||||
| 'git-repo-config' [type] --unset-all name [value_regex] | ||||
| 'git-repo-config' -l | --list | ||||
|  | ||||
| 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, | ||||
| no checks or transformations are performed on the value. | ||||
|  | ||||
| This command will fail if | ||||
| This command will fail if: | ||||
|  | ||||
| . .git/config is invalid, | ||||
| . .git/config can not be written to, | ||||
| . The .git/config file is invalid, | ||||
| . Can not write to .git/config, | ||||
| . no section was provided, | ||||
| . the section or key is invalid, | ||||
| . you try to unset an option which does not exist, or | ||||
|  | @ -48,7 +49,7 @@ OPTIONS | |||
|  | ||||
| --replace-all:: | ||||
| 	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 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 | ||||
| 	is not exactly one. | ||||
|  | ||||
| --get-regexp:: | ||||
| 	Like --get-all, but interprets the name as a regular expression. | ||||
|  | ||||
| --unset:: | ||||
| 	Remove the line matching the key from .git/config. | ||||
|  | ||||
| --unset-all:: | ||||
| 	Remove all matching lines from .git/config. | ||||
|  | ||||
| -l, --list:: | ||||
| 	List all variables set in .git/config. | ||||
|  | ||||
|  | ||||
| EXAMPLE | ||||
| ------- | ||||
|  | @ -87,11 +94,11 @@ Given a .git/config like this: | |||
| 		renames = true | ||||
|  | ||||
| 	; Proxy settings | ||||
| 	[proxy] | ||||
| 		command="ssh" for "ssh://kernel.org/" | ||||
| 		command="proxy-command" for kernel.org | ||||
| 		command="myprotocol-command" for "my://" | ||||
| 		command=default-proxy ; for all the rest | ||||
| 	[core] | ||||
| 		gitproxy="ssh" for "ssh://kernel.org/" | ||||
| 		gitproxy="proxy-command" for kernel.org | ||||
| 		gitproxy="myprotocol-command" for "my://" | ||||
| 		gitproxy=default-proxy ; for all the rest | ||||
|  | ||||
| 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". | ||||
|  | ||||
| ------------ | ||||
| % 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. | ||||
|  | @ -115,7 +122,7 @@ To delete the entry for renames, do | |||
| % git repo-config --unset diff.renames | ||||
| ------------ | ||||
|  | ||||
| If you want to delete an entry for a multivar (like proxy.command above), | ||||
| 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. | ||||
|  | ||||
| To query the value for a given key, do | ||||
|  | @ -133,27 +140,27 @@ or | |||
| 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: | ||||
|  | ||||
| ------------ | ||||
| % 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 | ||||
|  | ||||
| ------------ | ||||
| % 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, | ||||
| 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 | ||||
|  | @ -163,13 +170,16 @@ To actually match only values with an exclamation mark, you have to | |||
| ------------ | ||||
|  | ||||
|  | ||||
| include::config.txt[] | ||||
|  | ||||
|  | ||||
| Author | ||||
| ------ | ||||
| Written by Johannes Schindelin <Johannes.Schindelin@gmx.de> | ||||
|  | ||||
| Documentation | ||||
| -------------- | ||||
| Documentation by Johannes Schindelin. | ||||
| Documentation by Johannes Schindelin, Petr Baudis and the git-list <git@vger.kernel.org>. | ||||
|  | ||||
| GIT | ||||
| --- | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ OPTIONS | |||
| 	Commit to make the current HEAD. | ||||
|  | ||||
| Examples | ||||
| ~~~~~~~~ | ||||
| -------- | ||||
|  | ||||
| Undo a commit and redo:: | ||||
| + | ||||
|  | @ -52,7 +52,8 @@ $ git commit ... | |||
| $ git reset --soft HEAD^      <1> | ||||
| $ edit                        <2> | ||||
| $ git commit -a -c ORIG_HEAD  <3> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> This is most often done when you remembered what you | ||||
| just committed is incomplete, or you misspelled your commit | ||||
| message, or both.  Leaves working tree as it was before "reset". | ||||
|  | @ -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 | ||||
| commit by starting with its log message.  If you do not need to | ||||
| edit the message further, you can give -C option instead. | ||||
| ------------ | ||||
|  | ||||
| Undo commits permanently:: | ||||
| + | ||||
| ------------ | ||||
| $ git commit ... | ||||
| $ git reset --hard HEAD~3   <1> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad | ||||
| and you do not want to ever see them again.  Do *not* do this if | ||||
| you have already given these commits to somebody else. | ||||
| ------------ | ||||
|  | ||||
| Undo a commit, making it a topic branch:: | ||||
| + | ||||
|  | @ -79,14 +79,14 @@ Undo a commit, making it a topic branch:: | |||
| $ git branch topic/wip     <1> | ||||
| $ git reset --hard HEAD~3  <2> | ||||
| $ git checkout topic/wip   <3> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> You have made some commits, but realize they were premature | ||||
| to be in the "master" branch.  You want to continue polishing | ||||
| them in a topic branch, so create "topic/wip" branch off of the | ||||
| current HEAD. | ||||
| <2> Rewind the master branch to get rid of those three commits. | ||||
| <3> Switch to "topic/wip" branch and keep working. | ||||
| ------------ | ||||
|  | ||||
| Undo update-index:: | ||||
| + | ||||
|  | @ -96,7 +96,8 @@ $ git-update-index frotz.c filfre.c | |||
| $ mailx                                    <2> | ||||
| $ git reset                                <3> | ||||
| $ git pull git://info.example.com/ nitfol  <4> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> you are happily working on something, and find the changes | ||||
| in these files are in good order.  You do not want to see them | ||||
| when you run "git diff", because you plan to work on other files | ||||
|  | @ -109,7 +110,6 @@ index changes for these two files.  Your changes in working tree | |||
| remain there. | ||||
| <4> then you can pull and merge, leaving frotz.c and filfre.c | ||||
| changes still in the working tree. | ||||
| ------------ | ||||
|  | ||||
| Undo a merge or pull:: | ||||
| + | ||||
|  | @ -123,19 +123,18 @@ Auto-merging nitfol | |||
| CONFLICT (content): Merge conflict in nitfol | ||||
| Automatic merge failed/prevented; fix up by hand | ||||
| $ 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 | ||||
| conflicts; you were not ready to spend a lot of time merging | ||||
| right now, so you decide to do that later. | ||||
| <2> "pull" has not made merge commit, so "git reset --hard" | ||||
| which is a synonym for "git reset --hard HEAD" clears the mess | ||||
| from the index file and the working tree. | ||||
|  | ||||
| $ git pull . topic/branch <3> | ||||
| Updating from 41223... to 13134... | ||||
| Fast forward | ||||
| $ git reset --hard ORIG_HEAD <4> | ||||
|  | ||||
| <3> merge a topic branch into the current branch, which resulted | ||||
| in a fast forward. | ||||
| <4> but you decided that the topic branch is not ready for public | ||||
|  | @ -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 | ||||
| brings your index file and the working tree back to that state, | ||||
| and resets the tip of the branch to that commit. | ||||
| ------------ | ||||
|  | ||||
| Interrupted workflow:: | ||||
| + | ||||
|  | @ -162,14 +160,14 @@ $ git commit ;# commit with real log | |||
| $ git checkout feature | ||||
| $ git reset --soft HEAD^ ;# go back to WIP state  <2> | ||||
| $ git reset                                       <3> | ||||
|  | ||||
| ------------ | ||||
| + | ||||
| <1> This commit will get blown away so a throw-away log message is OK. | ||||
| <2> This removes the 'WIP' commit from the commit history, and sets | ||||
|     your working tree to the state just before you made that snapshot. | ||||
| <3> After <2>, the index file still has all the WIP changes you | ||||
|     committed in <1>.  This sets it to the last commit you were | ||||
|     basing the WIP changes on. | ||||
| ------------ | ||||
| <3> At this point the index file still has all the WIP changes you | ||||
|     committed as 'snapshot WIP'.  This updates the index to show your | ||||
|     WIP files as uncommitted. | ||||
|  | ||||
| Author | ||||
| ------ | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ OPTIONS | |||
| -v:: | ||||
|         Be verbose. | ||||
|  | ||||
| --:: | ||||
| \--:: | ||||
| 	This option can be used to separate command-line options from | ||||
| 	the list of files, (useful when filenames might be mistaken | ||||
| 	for command-line options). | ||||
|  |  | |||
|  | @ -13,9 +13,16 @@ SYNOPSIS | |||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
| Reads a packed archive (.pack) from the standard input, and | ||||
| expands the objects contained in the pack into "one-file | ||||
| one-object" format in $GIT_OBJECT_DIRECTORY. | ||||
| Read a packed archive (.pack) from the standard input, expanding | ||||
| the objects contained within and writing them into the repository in | ||||
| "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 | ||||
| ------- | ||||
|  |  | |||
|  | @ -11,11 +11,11 @@ SYNOPSIS | |||
| [verse] | ||||
| 'git-update-index' | ||||
| 	     [--add] [--remove | --force-remove] [--replace] | ||||
| 	     [--refresh [-q] [--unmerged] [--ignore-missing]] | ||||
| 	     [--refresh] [-q] [--unmerged] [--ignore-missing] | ||||
| 	     [--cacheinfo <mode> <object> <file>]\* | ||||
| 	     [--chmod=(+|-)x] | ||||
| 	     [--assume-unchanged | --no-assume-unchanged] | ||||
| 	     [--really-refresh] | ||||
| 	     [--really-refresh] [--unresolve] | ||||
| 	     [--info-only] [--index-info] | ||||
| 	     [-z] [--stdin] | ||||
| 	     [--verbose] | ||||
|  | @ -80,6 +80,10 @@ OPTIONS | |||
| 	filesystem that has very slow lstat(2) system call | ||||
| 	(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:: | ||||
| 	Do not create objects in the object database for all | ||||
| 	<file> arguments that follow this flag; just insert | ||||
|  | @ -109,7 +113,7 @@ OPTIONS | |||
| 	Only meaningful with `--stdin`; paths are separated with | ||||
| 	NUL character instead of LF. | ||||
|  | ||||
| --:: | ||||
| \--:: | ||||
| 	Do not interpret any more arguments as options. | ||||
|  | ||||
| <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 | ||||
| ---------------- | ||||
|  | ||||
| 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 --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 diff --name-only                           <9> | ||||
| 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. | ||||
| <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. | ||||
| <6> and it is assumed unchanged. | ||||
| <7> even after you edit it. | ||||
| <8> you can tell about the change after the fact. | ||||
| <9> now it checks with lstat(2) and finds it has been changed. | ||||
| ------------ | ||||
|  | ||||
|  | ||||
| Configuration | ||||
|  |  | |||
|  | @ -17,7 +17,10 @@ Prints a git logical variable. | |||
| OPTIONS | ||||
| ------- | ||||
| -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 | ||||
| -------- | ||||
|  | @ -46,6 +49,7 @@ See Also | |||
| -------- | ||||
| gitlink:git-commit-tree[1] | ||||
| gitlink:git-tag[1] | ||||
| gitlink:git-repo-config[1] | ||||
|  | ||||
| Author | ||||
| ------ | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ OPTIONS | |||
| -v:: | ||||
| 	After verifying the pack, show list of objects contained | ||||
| 	in the pack. | ||||
| --:: | ||||
| \--:: | ||||
| 	Do not interpret any more arguments as options. | ||||
|  | ||||
| OUTPUT FORMAT | ||||
|  |  | |||
|  | @ -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 | ||||
| 	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'. | ||||
| 	The "--" is necessary to avoid confusion with the *branch* named | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ gitk v2.6.12.. include/scsi drivers/scsi:: | |||
| 	Show as the changes since version 'v2.6.12' that changed any | ||||
| 	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'. | ||||
| 	The "--" is necessary to avoid confusion with the *branch* named | ||||
|  |  | |||
|  | @ -1,39 +1,71 @@ | |||
| object:: | ||||
| 	The unit of storage in git. It is uniquely identified by | ||||
| 	the SHA1 of its contents. Consequently, an object can not | ||||
| 	be changed. | ||||
| alternate object database:: | ||||
| 	Via the alternates mechanism, a repository can inherit part of its | ||||
| 	object database from another object database, which is called | ||||
| 	"alternate". | ||||
|  | ||||
| object name:: | ||||
| 	The unique identifier of an object. The hash of the object's contents | ||||
| 	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). | ||||
|  | ||||
| SHA1:: | ||||
| 	Synonym for object name. | ||||
|  | ||||
| object identifier:: | ||||
| 	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/`. | ||||
| bare repository:: | ||||
| 	A bare repository is normally an appropriately named | ||||
| 	directory with a `.git` suffix that does not have a | ||||
| 	locally checked-out copy of any of the files under revision | ||||
| 	control.  That is, all of the `git` administrative and | ||||
| 	control files that would normally be present in the | ||||
| 	hidden `.git` sub-directory are directly present in | ||||
| 	the `repository.git` directory instead, and no other files | ||||
| 	are present and checked out.  Usually publishers of public | ||||
| 	repositories make bare repositories available. | ||||
|  | ||||
| blob object:: | ||||
| 	Untyped object, e.g. the contents of a file. | ||||
|  | ||||
| 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. | ||||
| branch:: | ||||
| 	A non-cyclical graph of revisions, i.e. the complete history of | ||||
| 	a particular revision, which is called the branch head. The | ||||
| 	branch heads are stored in `$GIT_DIR/refs/heads/`. | ||||
|  | ||||
| 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). | ||||
| cache:: | ||||
| 	Obsolete for: index. | ||||
|  | ||||
| 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:: | ||||
| 	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 | ||||
| 	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:: | ||||
| 	A collection of files with stat information, whose contents are | ||||
| 	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 | ||||
| 	that file). | ||||
|  | ||||
| unmerged index: | ||||
| 	An index which contains unmerged index entries. | ||||
| master:: | ||||
| 	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:: | ||||
| 	Obsolete for: index. | ||||
| merge:: | ||||
| 	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:: | ||||
| 	The set of files and directories currently being worked on, | ||||
| 	i.e. you can work in your working tree without using git at all. | ||||
| object:: | ||||
| 	The unit of storage in git. It is uniquely identified by | ||||
| 	the SHA1 of its contents. Consequently, an object can not | ||||
| 	be changed. | ||||
|  | ||||
| directory:: | ||||
| 	The list you get with "ls" :-) | ||||
| 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/`. | ||||
|  | ||||
| revision:: | ||||
| 	A particular state of files and directories which was stored in | ||||
| 	the object database. It is referenced by a commit object. | ||||
| object identifier:: | ||||
| 	Synonym for object name. | ||||
|  | ||||
| checkout:: | ||||
| 	The action of updating the working tree to a revision which was | ||||
| 	stored in the object database. | ||||
| object name:: | ||||
| 	The unique identifier of an object. The hash of the object's contents | ||||
| 	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:: | ||||
| 	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. | ||||
| object type: | ||||
| 	One of the identifiers "commit","tree","tag" and "blob" describing | ||||
| 	the type of an 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. | ||||
| octopus:: | ||||
| 	To merge more than two branches. Also denotes an intelligent | ||||
| 	predator. | ||||
|  | ||||
| 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:: | ||||
| 	A commit object contains a (possibly empty) list of the logical | ||||
| 	predecessor(s) in the line of development, i.e. 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. | ||||
| pickaxe:: | ||||
| 	The term pickaxe refers to an option to the diffcore routines | ||||
| 	that help select changes that add or delete a given text string. | ||||
| 	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:: | ||||
| 	A working tree is clean, if it corresponds to the revision | ||||
| 	referenced by the current head. | ||||
| plumbing:: | ||||
| 	Cute name for core git. | ||||
|  | ||||
| dirty:: | ||||
| 	A working tree is said to be dirty if it contains modifications | ||||
| 	which have not been committed to the current branch. | ||||
| 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. | ||||
|  | ||||
| head:: | ||||
| 	The top of a branch. It contains a ref to the corresponding | ||||
| 	commit object. | ||||
| pull:: | ||||
| 	Pulling a branch means to fetch it and merge it. | ||||
|  | ||||
| branch:: | ||||
| 	A non-cyclical graph of revisions, i.e. the complete history of | ||||
| 	a particular revision, which is called the branch head. The | ||||
| 	branch heads are stored in `$GIT_DIR/refs/heads/`. | ||||
| 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. | ||||
|  | ||||
| master:: | ||||
| 	The default branch. Whenever you create a git repository, a branch | ||||
| 	named "master" is created, and becomes the active branch. In most | ||||
| 	cases, this contains the local development. | ||||
| reachable:: | ||||
| 	An object is reachable from a ref/commit/tree/tag, if there is a | ||||
| 	chain leading from the latter to the former. | ||||
|  | ||||
| origin:: | ||||
| 	The default upstream branch. Most projects have one upstream | ||||
| 	project which they track, and by default 'origin' is used for | ||||
| 	that purpose.  New updates from upstream will be fetched into | ||||
| 	this branch; you should never commit to it yourself. | ||||
| 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. | ||||
|  | ||||
| ref:: | ||||
| 	A 40-byte hex representation of a SHA1 pointing to a particular | ||||
| 	object. These may be stored in `$GIT_DIR/refs/`. | ||||
| 	A 40-byte hex representation of a SHA1 or a name that denotes | ||||
| 	a particular object. These may be stored in `$GIT_DIR/refs/`. | ||||
|  | ||||
| head ref:: | ||||
| 	A ref pointing to a head. Often, this is abbreviated to "head". | ||||
| 	Head refs are stored in `$GIT_DIR/refs/heads/`. | ||||
| refspec:: | ||||
| 	A refspec is used by fetch and push to describe the mapping | ||||
| 	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:: | ||||
| 	A ref pointing to either a commit object, a tree object, or a | ||||
| 	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:: | ||||
| 	An object containing a ref pointing to another object, which can | ||||
| 	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 | ||||
| 	commit ancestry chain. | ||||
|  | ||||
| merge:: | ||||
| 	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. | ||||
| unmerged index: | ||||
| 	An index which contains unmerged index entries. | ||||
|  | ||||
| octopus:: | ||||
| 	To merge more than two branches. Also denotes an intelligent | ||||
| 	predator. | ||||
|  | ||||
| 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. | ||||
| working tree:: | ||||
| 	The set of files and directories currently being worked on, | ||||
| 	i.e. you can work in your working tree without using git at all. | ||||
|  | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ This list is sorted alphabetically: | |||
| '; | ||||
|  | ||||
| @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) { | ||||
| 	$terms{$key}=~s/$pattern/sprintf "<<ref_".no_spaces($1).",$1>>";/eg; | ||||
| 	print '[[ref_'.no_spaces($key).']]'.$key."::\n" | ||||
|  |  | |||
							
								
								
									
										36
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										36
									
								
								Makefile
								
								
								
								
							|  | @ -28,8 +28,8 @@ all: | |||
| # | ||||
| # Define NO_SETENV if you don't have setenv in the C library. | ||||
| # | ||||
| # Define USE_SYMLINK_HEAD if you want .git/HEAD to be a symbolic link. | ||||
| # Don't enable it on Windows. | ||||
| # Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link. | ||||
| # Enable it on Windows.  By default, symrefs are still used. | ||||
| # | ||||
| # Define PPC_SHA1 environment variable when running make to make use of | ||||
| # a bundled SHA1 routine optimized for PowerPC. | ||||
|  | @ -115,13 +115,13 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ | |||
| SCRIPT_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-count-objects.sh git-diff.sh git-fetch.sh \ | ||||
| 	git-fetch.sh \ | ||||
| 	git-format-patch.sh git-ls-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-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-merge.sh git-merge-stupid.sh git-merge-octopus.sh \ | ||||
| 	git-merge-resolve.sh git-merge-ours.sh git-grep.sh \ | ||||
|  | @ -139,7 +139,7 @@ SCRIPT_PYTHON = \ | |||
| SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ | ||||
| 	  $(patsubst %.perl,%,$(SCRIPT_PERL)) \ | ||||
| 	  $(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. | ||||
| SIMPLE_PROGRAMS = \ | ||||
|  | @ -167,7 +167,8 @@ PROGRAMS = \ | |||
| 	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 | ||||
|  | ||||
| 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 | ||||
| ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS) | ||||
|  | @ -199,7 +200,7 @@ LIB_H = \ | |||
| 	tree-walk.h log-tree.h | ||||
|  | ||||
| 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-delta.o log-tree.o | ||||
|  | ||||
|  | @ -214,7 +215,7 @@ LIB_OBJS = \ | |||
| 	$(DIFF_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) | ||||
| LIBS = $(GITLIBS) -lz | ||||
|  | @ -263,6 +264,7 @@ ifeq ($(uname_O),Cygwin) | |||
| 	NO_D_TYPE_IN_DIRENT = YesPlease | ||||
| 	NO_D_INO_IN_DIRENT = YesPlease | ||||
| 	NO_STRCASESTR = YesPlease | ||||
| 	NO_SYMLINK_HEAD = YesPlease | ||||
| 	NEEDS_LIBICONV = YesPlease | ||||
| 	# There are conflicting reports about this. | ||||
| 	# On some boxes NO_MMAP is needed, and not so elsewhere. | ||||
|  | @ -386,6 +388,9 @@ endif | |||
| ifdef NO_D_INO_IN_DIRENT | ||||
| 	ALL_CFLAGS += -DNO_D_INO_IN_DIRENT | ||||
| endif | ||||
| ifdef NO_SYMLINK_HEAD | ||||
| 	ALL_CFLAGS += -DNO_SYMLINK_HEAD | ||||
| endif | ||||
| ifdef NO_STRCASESTR | ||||
| 	COMPAT_CFLAGS += -DNO_STRCASESTR | ||||
| 	COMPAT_OBJS += compat/strcasestr.o | ||||
|  | @ -470,6 +475,8 @@ git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) | |||
| 		$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \ | ||||
| 		$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) | ||||
|  | ||||
| builtin-help.o: common-cmds.h | ||||
|  | ||||
| $(BUILT_INS): git$X | ||||
| 	rm -f $@ && ln git$X $@ | ||||
|  | ||||
|  | @ -503,9 +510,6 @@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py | |||
| git-cherry-pick: git-revert | ||||
| 	cp $< $@ | ||||
|  | ||||
| git-show: git-whatchanged | ||||
| 	cp $< $@ | ||||
|  | ||||
| git-status: git-commit | ||||
| 	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,$^) \ | ||||
| 		$(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 | ||||
| 	$(CC) -c $(ALL_CFLAGS) \ | ||||
| 		-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c | ||||
|  | @ -573,12 +573,12 @@ $(patsubst git-%$X,%.o,$(PROGRAMS)): $(GITLIBS) | |||
| $(DIFF_OBJS): diffcore.h | ||||
|  | ||||
| $(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_LIB): $(XDIFF_OBJS) | ||||
| 	$(AR) rcs $@ $(XDIFF_OBJS) | ||||
| 	rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS) | ||||
|  | ||||
|  | ||||
| doc: | ||||
|  |  | |||
							
								
								
									
										10
									
								
								blame.c
								
								
								
								
							
							
						
						
									
										10
									
								
								blame.c
								
								
								
								
							|  | @ -515,9 +515,9 @@ static int compare_tree_path(struct rev_info* revs, | |||
| 	paths[1] = NULL; | ||||
|  | ||||
| 	diff_tree_setup_paths(get_pathspec(revs->prefix, paths), | ||||
| 			      &revs->diffopt); | ||||
| 			      &revs->pruning); | ||||
| 	ret = rev_compare_tree(revs, c1->tree, c2->tree); | ||||
| 	diff_tree_release_paths(&revs->diffopt); | ||||
| 	diff_tree_release_paths(&revs->pruning); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|  | @ -531,9 +531,9 @@ static int same_tree_as_empty_path(struct rev_info *revs, struct tree* t1, | |||
| 	paths[1] = NULL; | ||||
|  | ||||
| 	diff_tree_setup_paths(get_pathspec(revs->prefix, paths), | ||||
| 			      &revs->diffopt); | ||||
| 			      &revs->pruning); | ||||
| 	ret = rev_same_tree_as_empty(revs, t1); | ||||
| 	diff_tree_release_paths(&revs->diffopt); | ||||
| 	diff_tree_release_paths(&revs->pruning); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|  | @ -834,7 +834,7 @@ int main(int argc, const char **argv) | |||
|  | ||||
| 	args[0] = filename; | ||||
| 	args[1] = NULL; | ||||
| 	diff_tree_setup_paths(args, &rev.diffopt); | ||||
| 	diff_tree_setup_paths(args, &rev.pruning); | ||||
| 	prepare_revision_walk(&rev); | ||||
| 	process_commits(&rev, filename, &initial); | ||||
|  | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  | @ -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); | ||||
| } | ||||
|  | @ -3,6 +3,7 @@ | |||
|  * | ||||
|  * Builtin help-related commands (help, usage, version) | ||||
|  */ | ||||
| #include <sys/ioctl.h> | ||||
| #include "cache.h" | ||||
| #include "builtin.h" | ||||
| #include "exec_cmd.h" | ||||
|  |  | |||
|  | @ -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); | ||||
| } | ||||
|  | @ -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_show(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_count_objects(int argc, const char **argv, char **envp); | ||||
|  | ||||
| extern int cmd_push(int argc, const char **argv, char **envp); | ||||
|  | ||||
| #endif | ||||
|  |  | |||
							
								
								
									
										4
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										4
									
								
								cache.h
								
								
								
								
							|  | @ -134,6 +134,8 @@ extern const char *setup_git_directory_gently(int *); | |||
| extern const char *setup_git_directory(void); | ||||
| 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 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) | ||||
|  | ||||
|  | @ -167,7 +169,7 @@ extern void rollback_index_file(struct cache_file *); | |||
| /* Environment bits from configuration mechanism */ | ||||
| extern int trust_executable_bit; | ||||
| extern int assume_unchanged; | ||||
| extern int only_use_symrefs; | ||||
| extern int prefer_symlink_refs; | ||||
| extern int warn_ambiguous_refs; | ||||
| extern int diff_rename_limit_default; | ||||
| extern int shared_repository; | ||||
|  |  | |||
|  | @ -269,12 +269,16 @@ int main(int argc, char **argv) | |||
| 	/* Check out named files first */ | ||||
| 	for ( ; i < argc; i++) { | ||||
| 		const char *arg = argv[i]; | ||||
| 		const char *p; | ||||
|  | ||||
| 		if (all) | ||||
| 			die("git-checkout-index: don't mix '--all' and explicit filenames"); | ||||
| 		if (read_from_stdin) | ||||
| 			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) { | ||||
|  | @ -284,6 +288,8 @@ int main(int argc, char **argv) | |||
| 		strbuf_init(&buf); | ||||
| 		while (1) { | ||||
| 			char *path_name; | ||||
| 			const char *p; | ||||
|  | ||||
| 			read_line(&buf, stdin, line_termination); | ||||
| 			if (buf.eof) | ||||
| 				break; | ||||
|  | @ -291,7 +297,10 @@ int main(int argc, char **argv) | |||
| 				path_name = unquote_c_style(buf.buf, NULL); | ||||
| 			else | ||||
| 				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) | ||||
| 				free(path_name); | ||||
| 		} | ||||
|  |  | |||
|  | @ -831,15 +831,16 @@ void show_combined_diff(struct combine_diff_path *p, | |||
| 	} | ||||
| } | ||||
|  | ||||
| void diff_tree_combined_merge(const unsigned char *sha1, | ||||
| 			     int dense, struct rev_info *rev) | ||||
| void diff_tree_combined(const unsigned char *sha1, | ||||
| 			const unsigned char parent[][20], | ||||
| 			int num_parent, | ||||
| 			int dense, | ||||
| 			struct rev_info *rev) | ||||
| { | ||||
| 	struct diff_options *opt = &rev->diffopt; | ||||
| 	struct commit *commit = lookup_commit(sha1); | ||||
| 	struct diff_options diffopts; | ||||
| 	struct commit_list *parents; | ||||
| 	struct combine_diff_path *p, *paths = NULL; | ||||
| 	int num_parent, i, num_paths; | ||||
| 	int i, num_paths; | ||||
| 	int do_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.recursive = 1; | ||||
|  | ||||
| 	/* count parents */ | ||||
| 	for (parents = commit->parents, num_parent = 0; | ||||
| 	     parents; | ||||
| 	     parents = parents->next, num_parent++) | ||||
| 		; /* nothing */ | ||||
|  | ||||
| 	/* find set of paths that everybody touches */ | ||||
| 	for (parents = commit->parents, i = 0; | ||||
| 	     parents; | ||||
| 	     parents = parents->next, i++) { | ||||
| 		struct commit *parent = parents->item; | ||||
| 	for (i = 0; i < num_parent; i++) { | ||||
| 		/* show stat against the first parent even | ||||
| 		 * when doing combined diff. | ||||
| 		 */ | ||||
|  | @ -867,8 +859,7 @@ void diff_tree_combined_merge(const unsigned char *sha1, | |||
| 			diffopts.output_format = DIFF_FORMAT_DIFFSTAT; | ||||
| 		else | ||||
| 			diffopts.output_format = DIFF_FORMAT_NO_OUTPUT; | ||||
| 		diff_tree_sha1(parent->object.sha1, commit->object.sha1, "", | ||||
| 			       &diffopts); | ||||
| 		diff_tree_sha1(parent[i], sha1, "", &diffopts); | ||||
| 		diffcore_std(&diffopts); | ||||
| 		paths = intersect_paths(paths, i, num_parent); | ||||
|  | ||||
|  | @ -907,3 +898,25 @@ void diff_tree_combined_merge(const unsigned char *sha1, | |||
| 		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); | ||||
| } | ||||
|  |  | |||
|  | @ -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) | ||||
| { | ||||
| 	void *buf; | ||||
| 	char type[20]; | ||||
| 	unsigned long size; | ||||
|  | ||||
| 	buf = read_sha1_file(sha1, type, &size); | ||||
| 	if (!buf || strcmp(type, expect)) | ||||
| 		die("%s is not a valid '%s' object", sha1_to_hex(sha1), expect); | ||||
| 	free(buf); | ||||
| 	if (sha1_object_info(sha1, type, NULL)) | ||||
| 		die("%s is not a valid object", sha1_to_hex(sha1)); | ||||
| 	if (expect && strcmp(type, expect)) | ||||
| 		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); | ||||
|  | ||||
| 	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); | ||||
|  | ||||
| 	check_valid(tree_sha1, tree_type); | ||||
|  |  | |||
							
								
								
									
										23
									
								
								config.c
								
								
								
								
							
							
						
						
									
										23
									
								
								config.c
								
								
								
								
							|  | @ -60,6 +60,12 @@ static char *parse_value(void) | |||
| 			space = 1; | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!quote) { | ||||
| 			if (c == ';' || c == '#') { | ||||
| 				comment = 1; | ||||
| 				continue; | ||||
| 			} | ||||
| 		} | ||||
| 		if (space) { | ||||
| 			if (len) | ||||
| 				value[len++] = ' '; | ||||
|  | @ -93,12 +99,6 @@ static char *parse_value(void) | |||
| 			quote = 1-quote; | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!quote) { | ||||
| 			if (c == ';' || c == '#') { | ||||
| 				comment = 1; | ||||
| 				continue; | ||||
| 			} | ||||
| 		} | ||||
| 		value[len++] = c; | ||||
| 	} | ||||
| } | ||||
|  | @ -227,8 +227,8 @@ int git_default_config(const char *var, const char *value) | |||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (!strcmp(var, "core.symrefsonly")) { | ||||
| 		only_use_symrefs = git_config_bool(var, value); | ||||
| 	if (!strcmp(var, "core.prefersymlinkrefs")) { | ||||
| 		prefer_symlink_refs = git_config_bool(var, value); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
|  | @ -252,7 +252,7 @@ int git_default_config(const char *var, const char *value) | |||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Add other config variables here.. */ | ||||
| 	/* Add other config variables here and to Documentation/config.txt. */ | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | @ -335,8 +335,11 @@ static int store_aux(const char* key, const char* value) | |||
| 			store.offset[store.seen] = ftell(config_file); | ||||
| 			store.state = KEY_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.offset[store.seen] = ftell(config_file); | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,2 @@ | |||
| This is "colordiff" (http://colordiff.sourceforge.net/) by Dave | ||||
| Ewart <davee@sungate.co.uk>, modified specifically for git. | ||||
|  | @ -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}"; | ||||
| } | ||||
|  | @ -8,7 +8,7 @@ use vars qw/	$AUTHOR $VERSION | |||
| 		$GIT_SVN_INDEX $GIT_SVN | ||||
| 		$GIT_DIR $REV_DIR/; | ||||
| $AUTHOR = 'Eric Wong <normalperson@yhbt.net>'; | ||||
| $VERSION = '0.11.0'; | ||||
| $VERSION = '1.0.0'; | ||||
|  | ||||
| use Cwd qw/abs_path/; | ||||
| $GIT_DIR = abs_path($ENV{GIT_DIR} || '.git'); | ||||
|  | @ -42,7 +42,8 @@ my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext, | |||
| my %cmd = ( | ||||
| 	fetch => [ \&fetch, "Download new revisions from SVN", | ||||
| 			{ '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", | ||||
| 			{	'stdin|' => \$_stdin, | ||||
| 				'edit|e' => \$_edit, | ||||
|  | @ -220,7 +221,8 @@ when you have upgraded your tools and habits to use refs/remotes/$GIT_SVN | |||
| } | ||||
|  | ||||
| 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) { | ||||
| 		sys('git-init-db'); | ||||
| 	} | ||||
|  |  | |||
|  | @ -36,17 +36,22 @@ COMMANDS | |||
| -------- | ||||
| init:: | ||||
| 	Creates an empty git repository with additional metadata | ||||
| 	directories for git-svn.  The SVN_URL must be specified | ||||
| 	at this point. | ||||
| 	directories for git-svn.  The Subversion URL must be specified | ||||
| 	as a command-line argument. | ||||
|  | ||||
| fetch:: | ||||
| 	Fetch unfetched revisions from the SVN_URL we are tracking. | ||||
| 	refs/heads/remotes/git-svn will be updated to the latest revision. | ||||
| 	Fetch unfetched revisions from the Subversion URL we are | ||||
| 	tracking.  refs/remotes/git-svn will be updated to the | ||||
| 	latest revision. | ||||
|  | ||||
| 	Note: You should never attempt to modify the remotes/git-svn branch | ||||
| 	outside of git-svn.  Instead, create a branch from remotes/git-svn | ||||
| 	and work on that branch.  Use the 'commit' command (see below) | ||||
| 	to write git commits back to remotes/git-svn. | ||||
| 	Note: You should never attempt to modify the remotes/git-svn | ||||
| 	branch outside of git-svn.  Instead, create a branch from | ||||
| 	remotes/git-svn and work on that branch.  Use the 'commit' | ||||
| 	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 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 | ||||
| 	git-svn metadata and the svn working tree that git-svn uses for | ||||
| 	its operations.  This rebuilds the metadata so git-svn can | ||||
| 	resume fetch operations.  SVN_URL may be optionally specified if | ||||
| 	the directory/repository you're tracking has moved or changed | ||||
| 	protocols. | ||||
| 	resume fetch operations.  A Subversion URL may be optionally | ||||
| 	specified at the command-line if the directory/repository you're | ||||
| 	tracking has moved or changed protocols. | ||||
|  | ||||
| show-ignore:: | ||||
| 	Recursively finds and lists the svn:ignore property on | ||||
|  | @ -123,6 +128,24 @@ OPTIONS | |||
| 	repo-config key: svn.l | ||||
| 	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 | ||||
| ---------------- | ||||
| -b<refname>:: | ||||
|  |  | |||
							
								
								
									
										2
									
								
								daemon.c
								
								
								
								
							
							
						
						
									
										2
									
								
								daemon.c
								
								
								
								
							|  | @ -535,7 +535,7 @@ static int socksetup(int port, int **socklist_p) | |||
|  | ||||
| 		if (set_reuse_addr(sockfd)) { | ||||
| 			close(sockfd); | ||||
| 			return 0;	/* not fatal */ | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { | ||||
|  |  | |||
							
								
								
									
										6
									
								
								delta.h
								
								
								
								
							
							
						
						
									
										6
									
								
								delta.h
								
								
								
								
							|  | @ -2,11 +2,11 @@ | |||
| #define DELTA_H | ||||
|  | ||||
| /* handling of delta buffers */ | ||||
| extern void *diff_delta(void *from_buf, unsigned long from_size, | ||||
| 			void *to_buf, unsigned long to_size, | ||||
| extern void *diff_delta(const void *from_buf, unsigned long from_size, | ||||
| 			const void *to_buf, unsigned long to_size, | ||||
| 		        unsigned long *delta_size, unsigned long max_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); | ||||
|  | ||||
| /* the smallest possible delta size is 4 bytes */ | ||||
|  |  | |||
|  | @ -131,8 +131,8 @@ static struct index ** delta_index(const unsigned char *buf, | |||
| /* the maximum size for any opcode */ | ||||
| #define MAX_OP_SIZE COPYOP_SIZE(0xffffffff, 0xffffffff) | ||||
|  | ||||
| void *diff_delta(void *from_buf, unsigned long from_size, | ||||
| 		 void *to_buf, unsigned long to_size, | ||||
| void *diff_delta(const void *from_buf, unsigned long from_size, | ||||
| 		 const void *to_buf, unsigned long to_size, | ||||
| 		 unsigned long *delta_size, | ||||
| 		 unsigned long max_size) | ||||
| { | ||||
|  |  | |||
							
								
								
									
										206
									
								
								diff-files.c
								
								
								
								
							
							
						
						
									
										206
									
								
								diff-files.c
								
								
								
								
							|  | @ -12,203 +12,43 @@ static const char diff_files_usage[] = | |||
| "git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]" | ||||
| 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) | ||||
| { | ||||
| 	const char **pathspec; | ||||
| 	const char *prefix = setup_git_directory(); | ||||
| 	int entries, i; | ||||
| 	struct rev_info rev; | ||||
| 	int silent = 0; | ||||
|  | ||||
| 	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] == '-') { | ||||
| 		if (!strcmp(argv[1], "--")) { | ||||
| 			argv++; | ||||
| 			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; | ||||
| 		if (!strcmp(argv[1], "--base")) | ||||
| 			rev.max_count = 1; | ||||
| 		else if (!strcmp(argv[1], "--ours")) | ||||
| 			diff_unmerged_stage = 2; | ||||
| 			rev.max_count = 2; | ||||
| 		else if (!strcmp(argv[1], "--theirs")) | ||||
| 			diff_unmerged_stage = 3; | ||||
| 			rev.max_count = 3; | ||||
| 		else if (!strcmp(argv[1], "-q")) | ||||
| 			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 | ||||
| 			usage(diff_files_usage); | ||||
| 		} | ||||
| 		argv++; argc--; | ||||
| 	} | ||||
| 	if (dense_combined_merges) | ||||
| 		rev.diffopt.output_format = DIFF_FORMAT_PATCH; | ||||
|  | ||||
| 	/* Find the directory, and set up the pathspec */ | ||||
| 	pathspec = get_pathspec(prefix, argv + 1); | ||||
| 	entries = read_cache(); | ||||
|  | ||||
| 	if (diff_setup_done(&rev.diffopt) < 0) | ||||
| 	/* | ||||
| 	 * Make sure there are NO revision (i.e. pending object) parameter, | ||||
| 	 * rev.max_count is reasonable (0 <= n <= 3), | ||||
| 	 * there is no other revision filtering parameters. | ||||
| 	 */ | ||||
| 	if (rev.pending_objects || | ||||
| 	    rev.min_age != -1 || rev.max_age != -1) | ||||
| 		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 (combine_merges && num_compare_stages == 2) { | ||||
| 				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; | ||||
| 	if (rev.diffopt.output_format == DIFF_FORMAT_NO_OUTPUT) | ||||
| 		rev.diffopt.output_format = DIFF_FORMAT_RAW; | ||||
| 	return run_diff_files(&rev, silent); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										249
									
								
								diff-index.c
								
								
								
								
							
							
						
						
									
										249
									
								
								diff-index.c
								
								
								
								
							|  | @ -1,166 +1,7 @@ | |||
| #include "cache.h" | ||||
| #include "tree.h" | ||||
| #include "diff.h" | ||||
|  | ||||
| static int cached_only = 0; | ||||
| 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); | ||||
| 	} | ||||
| } | ||||
| #include "commit.h" | ||||
| #include "revision.h" | ||||
|  | ||||
| static const char diff_cache_usage[] = | ||||
| "git-diff-index [-m] [--cached] " | ||||
|  | @ -169,85 +10,29 @@ COMMON_DIFF_OPTIONS_HELP; | |||
|  | ||||
| int main(int argc, const char **argv) | ||||
| { | ||||
| 	const char *tree_name = NULL; | ||||
| 	unsigned char sha1[20]; | ||||
| 	const char *prefix = setup_git_directory(); | ||||
| 	const char **pathspec = NULL; | ||||
| 	struct tree *tree; | ||||
| 	int ret; | ||||
| 	int allow_options = 1; | ||||
| 	struct rev_info rev; | ||||
| 	int cached = 0; | ||||
| 	int i; | ||||
|  | ||||
| 	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++) { | ||||
| 		const char *arg = argv[i]; | ||||
| 		int diff_opt_cnt; | ||||
| 			 | ||||
| 		if (!allow_options || *arg != '-') { | ||||
| 			if (tree_name) | ||||
| 				break; | ||||
| 			tree_name = arg; | ||||
| 			continue; | ||||
| 		if (!strcmp(arg, "--cached")) | ||||
| 			cached = 1; | ||||
| 		else | ||||
| 			usage(diff_cache_usage); | ||||
| 	} | ||||
| 			 | ||||
| 		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 | ||||
| 			 * unmerged index could show something else | ||||
| 			 * later, but pretend --cc is the same as -p for | ||||
| 			 * now.  "git diff" uses --cc by default. | ||||
| 	 * Make sure there is one revision (i.e. pending object), | ||||
| 	 * and there is no revision filtering parameters. | ||||
| 	 */ | ||||
| 			argv[i] = arg = "-p"; | ||||
| 		diff_opt_cnt = diff_opt_parse(&diff_options, argv + i, | ||||
| 					      argc - i); | ||||
| 		if (diff_opt_cnt < 0) | ||||
| 	if (!rev.pending_objects || rev.pending_objects->next || | ||||
| 	    rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1) | ||||
| 		usage(diff_cache_usage); | ||||
| 		else if (diff_opt_cnt) { | ||||
| 			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; | ||||
| 	return run_diff_index(&rev, cached); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										1984
									
								
								diff-lib.c
								
								
								
								
							
							
						
						
									
										1984
									
								
								diff-lib.c
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										11
									
								
								diff.h
								
								
								
								
							
							
						
						
									
										11
									
								
								diff.h
								
								
								
								
							|  | @ -28,10 +28,11 @@ struct diff_options { | |||
| 		 with_raw:1, | ||||
| 		 with_stat:1, | ||||
| 		 tree_in_recursive:1, | ||||
| 		 full_index:1; | ||||
| 		 full_index:1, | ||||
| 		 silent_on_remove:1, | ||||
| 		 find_copies_harder:1; | ||||
| 	int break_opt; | ||||
| 	int detect_rename; | ||||
| 	int find_copies_harder; | ||||
| 	int line_termination; | ||||
| 	int output_format; | ||||
| 	int pickaxe_opts; | ||||
|  | @ -74,6 +75,8 @@ struct combine_diff_path { | |||
| extern void show_combined_diff(struct combine_diff_path *elem, int num_parent, | ||||
| 			      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_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 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 */ | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ char git_default_email[MAX_GITNAME]; | |||
| char git_default_name[MAX_GITNAME]; | ||||
| int trust_executable_bit = 1; | ||||
| int assume_unchanged = 0; | ||||
| int only_use_symrefs = 0; | ||||
| int prefer_symlink_refs = 0; | ||||
| int warn_ambiguous_refs = 1; | ||||
| int repository_format_version = 0; | ||||
| char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8"; | ||||
|  |  | |||
							
								
								
									
										31
									
								
								git-am.sh
								
								
								
								
							
							
						
						
									
										31
									
								
								git-am.sh
								
								
								
								
							|  | @ -14,6 +14,26 @@ stop_here () { | |||
|     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 () { | ||||
| 	rm -f "$dotest/$msgnum" "$dotest/msg" "$dotest/msg-clean" \ | ||||
| 		"$dotest/patch" "$dotest/info" | ||||
|  | @ -374,7 +394,14 @@ do | |||
| 		if test '' = "$changed" | ||||
| 		then | ||||
| 			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 | ||||
| 		apply_status=0 | ||||
| 		;; | ||||
|  | @ -400,7 +427,7 @@ do | |||
| 	if test $apply_status != 0 | ||||
| 	then | ||||
| 		echo Patch failed at $msgnum. | ||||
| 		stop_here $this | ||||
| 		stop_here_user_resolve $this | ||||
| 	fi | ||||
|  | ||||
| 	if test -x "$GIT_DIR"/hooks/pre-applypatch | ||||
|  |  | |||
|  | @ -10,9 +10,10 @@ use warnings; | |||
| use strict; | ||||
| use Getopt::Long; | ||||
| use POSIX qw(strftime gmtime); | ||||
| use File::Basename qw(basename dirname); | ||||
|  | ||||
| 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 | ||||
| 			Show long rev (Defaults off) | ||||
| 	-t, --time | ||||
|  | @ -23,7 +24,7 @@ sub usage() { | |||
| 			Use revs from revs-file instead of calling git-rev-list | ||||
| 	-h, --help | ||||
| 			This message. | ||||
| '; | ||||
| "; | ||||
|  | ||||
| 	exit(1); | ||||
| } | ||||
|  | @ -35,7 +36,7 @@ my $rc = GetOptions(	"long|l" => \$longrev, | |||
| 			"help|h" => \$help, | ||||
| 			"rename|r" => \$rename, | ||||
| 			"rev-file|S=s" => \$rev_file); | ||||
| if (!$rc or $help) { | ||||
| if (!$rc or $help or !@ARGV) { | ||||
| 	usage(); | ||||
| } | ||||
|  | ||||
|  | @ -208,6 +209,9 @@ sub find_parent_renames { | |||
| 	while (my $change = <$patch>) { | ||||
| 		chomp $change; | ||||
| 		my $filename = <$patch>; | ||||
| 		if (!defined $filename) { | ||||
| 			next; | ||||
| 		} | ||||
| 		chomp $filename; | ||||
|  | ||||
| 		if ($change =~ m/^[AMD]$/ ) { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| #!/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. | ||||
| 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>.' | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -88,7 +88,7 @@ my $TEMP_DIR = tempdir( CLEANUP => 1 ); | |||
| $log->debug("Temporary directory is '$TEMP_DIR'"); | ||||
|  | ||||
| # 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 | ||||
| if (@ARGV && $ARGV[0] eq 'pserver') { | ||||
|     my $line = <STDIN>; chomp $line; | ||||
|  | @ -117,7 +117,7 @@ while (<STDIN>) | |||
| { | ||||
|     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}) ) | ||||
|     { | ||||
|         # use the $methods hash to call the appropriate sub for this command | ||||
|  | @ -171,11 +171,11 @@ sub req_Root | |||
|        return 0; | ||||
|     } | ||||
|  | ||||
|     my @gitvars = `git-var -l`; | ||||
|     my @gitvars = `git-repo-config -l`; | ||||
|     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 "error 1 - problem executing git-var\n"; | ||||
|         print "error 1 - problem executing git-repo-config\n"; | ||||
|        return 0; | ||||
|     } | ||||
|     foreach my $line ( @gitvars ) | ||||
|  | @ -224,7 +224,7 @@ sub req_Globaloption | |||
| sub req_Validresponses | ||||
| { | ||||
|     my ( $cmd, $data ) = @_; | ||||
|     $log->debug("req_Validrepsonses : $data"); | ||||
|     $log->debug("req_Validresponses : $data"); | ||||
|  | ||||
|     # TODO : re-enable this, currently it's not particularly useful | ||||
|     #$state->{validresponses} = [ split /\s+/, $data ]; | ||||
|  | @ -733,7 +733,7 @@ sub req_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 | ||||
|     # at that. Eclipse uses this technique to offer you a list of | ||||
|     # projects (heads in this case) to checkout. | ||||
|  | @ -1731,7 +1731,7 @@ sub transmitfile | |||
| } | ||||
|  | ||||
| # 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 | ||||
| sub filenamesplit | ||||
| { | ||||
|  | @ -1790,7 +1790,7 @@ Log::Log4perl | |||
| =head2 new | ||||
|  | ||||
| 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 | ||||
| nofile. | ||||
|  | ||||
|  | @ -2076,14 +2076,15 @@ sub update | |||
|     # TODO: log processing is memory bound | ||||
|     # if we can parse into a 2nd file that is in reverse order | ||||
|     # 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) { | ||||
|         push @git_log_params, "$lastcommit..$self->{module}"; | ||||
|     } else { | ||||
|         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; | ||||
|  | ||||
|  | @ -2595,7 +2596,7 @@ sub in_array | |||
|  | ||||
| =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 | ||||
|  | ||||
| =cut | ||||
|  |  | |||
							
								
								
									
										74
									
								
								git-diff.sh
								
								
								
								
							
							
						
						
									
										74
									
								
								git-diff.sh
								
								
								
								
							|  | @ -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" | ||||
							
								
								
									
										12
									
								
								git-fetch.sh
								
								
								
								
							
							
						
						
									
										12
									
								
								git-fetch.sh
								
								
								
								
							|  | @ -270,12 +270,20 @@ fetch_main () { | |||
| 	  if [ -n "$GIT_SSL_NO_VERIFY" ]; then | ||||
| 	      curl_extra_args="-k" | ||||
| 	  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 ' | ||||
| 	      my $u = $ARGV[0]; | ||||
|               $u =~ s/^ref:\s*//; | ||||
| 	      $u =~ s{([^-a-zA-Z0-9/.])}{sprintf"%%%02x",ord($1)}eg; | ||||
| 	      print "$u"; | ||||
| 	  ' "$remote_name") | ||||
| 	  head=$(curl -nsfL $curl_extra_args "$remote/$remote_name_quoted") && | ||||
| 	  ' "$head") | ||||
| 	    head=$(curl -nsfL $curl_extra_args "$remote/$remote_name_quoted") | ||||
| 	    depth=$( expr \( $depth + 1 \) ) | ||||
| 	  done | ||||
| 	  expr "z$head" : "z$_x40\$" >/dev/null || | ||||
| 	      die "Failed to fetch $remote_name from $remote" | ||||
| 	  echo >&2 Fetching "$remote_name from $remote" using http | ||||
|  |  | |||
|  | @ -205,11 +205,10 @@ sub show_date { | |||
|     } | ||||
|     my $t = $time + $minutes * 60; | ||||
|     my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime($t); | ||||
|     return sprintf("%s %s %d %02d:%02d:%02d %d %+05d", | ||||
| 		   $weekday_names[$wday], | ||||
| 		   $month_names[$mon], | ||||
| 		   $mday, $hour, $min, $sec, | ||||
| 		   $year+1900, $tz); | ||||
|     return sprintf("%s, %d %s %d %02d:%02d:%02d %+05d", | ||||
| 		   $weekday_names[$wday], $mday, | ||||
| 		   $month_names[$mon], $year+1900, | ||||
| 		   $hour, $min, $sec, $tz); | ||||
| } | ||||
|  | ||||
| print "From nobody Mon Sep 17 00:00:00 2001\n"; | ||||
|  |  | |||
|  | @ -4,37 +4,51 @@ | |||
| # | ||||
|  | ||||
| USAGE='[--onto <newbase>] <upstream> [<branch>]' | ||||
| LONG_USAGE='git-rebase applies to <upstream> (or optionally to <newbase>) commits | ||||
| from <branch> that do not appear in <upstream>. When <branch> is not | ||||
| specified it defaults to the current branch (HEAD). | ||||
| LONG_USAGE='git-rebase replaces <branch> with a new branch of the | ||||
| same name.  When the --onto option is provided the new branch starts | ||||
| 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 | ||||
| newly created line of commit objects, so the previous line will not be | ||||
| accessible unless there are other references to it already. | ||||
| It is possible that a merge failure will prevent this process from being | ||||
| completely automatic.  You will have to resolve any such merge failure | ||||
| 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 | ||||
|          / | ||||
|     D---E---F---G master | ||||
| Example:       git-rebase master~1 topic | ||||
|  | ||||
| The result of the following command: | ||||
|  | ||||
|     git-rebase --onto master~1 master topic | ||||
|  | ||||
|   would be: | ||||
|  | ||||
|               A'\''--B'\''--C'\'' topic | ||||
|              / | ||||
|     D---E---F---G master | ||||
|         A---B---C topic                   A'\''--B'\''--C'\'' topic | ||||
|        /                   -->           / | ||||
|   D---E---F---G master          D---E---F---G master | ||||
| ' | ||||
|  | ||||
| . git-sh-setup | ||||
|  | ||||
| unset newbase | ||||
| while case "$#" in 0) break ;; esac | ||||
| do | ||||
| 	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) | ||||
| 		test 2 -le "$#" || usage | ||||
| 		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 | ||||
| # done only when upstream and onto are the same. | ||||
| if test "$upstream" = "onto" | ||||
| if test "$upstream" = "$onto" | ||||
| then | ||||
| 	mb=$(git-merge-base "$onto" "$branch") | ||||
| 	if test "$mb" = "$onto" | ||||
|  |  | |||
|  | @ -291,6 +291,13 @@ sub send_message | |||
| 	my $to = join (",\n\t", @recipients); | ||||
| 	@recipients = unique_email_list(@recipients,@cc); | ||||
| 	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 | ||||
| To: $to | ||||
|  | @ -299,7 +306,7 @@ Subject: $subject | |||
| Reply-To: $from | ||||
| Date: $date | ||||
| 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; | ||||
|  | ||||
|  |  | |||
|  | @ -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
								
								
								
								
							
							
						
						
									
										4
									
								
								git.c
								
								
								
								
							|  | @ -8,7 +8,6 @@ | |||
| #include <errno.h> | ||||
| #include <limits.h> | ||||
| #include <stdarg.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include "git-compat-util.h" | ||||
| #include "exec_cmd.h" | ||||
|  | ||||
|  | @ -47,7 +46,10 @@ static void handle_internal_command(int argc, const char **argv, char **envp) | |||
| 		{ "log", cmd_log }, | ||||
| 		{ "whatchanged", cmd_whatchanged }, | ||||
| 		{ "show", cmd_show }, | ||||
| 		{ "push", cmd_push }, | ||||
| 		{ "fmt-patch", cmd_format_patch }, | ||||
| 		{ "count-objects", cmd_count_objects }, | ||||
| 		{ "diff", cmd_diff }, | ||||
| 	}; | ||||
| 	int i; | ||||
|  | ||||
|  |  | |||
							
								
								
									
										16
									
								
								log-tree.c
								
								
								
								
							
							
						
						
									
										16
									
								
								log-tree.c
								
								
								
								
							|  | @ -3,6 +3,15 @@ | |||
| #include "commit.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) | ||||
| { | ||||
| 	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; | ||||
| 	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; | ||||
| 	} | ||||
|  | ||||
|  | @ -57,6 +69,8 @@ void show_log(struct rev_info *opt, struct log_info *log, const char *sep) | |||
| 		printf("%s%s", | ||||
| 		       opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ", | ||||
| 		       diff_unique_abbrev(commit->object.sha1, abbrev_commit)); | ||||
| 		if (opt->parents) | ||||
| 			show_parents(commit, abbrev_commit); | ||||
| 		if (parent)  | ||||
| 			printf(" (from %s)", | ||||
| 			       diff_unique_abbrev(parent->object.sha1, | ||||
|  |  | |||
|  | @ -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) | ||||
| { | ||||
| 	char branch1_sha1[50]; | ||||
|  | ||||
| 	/* If it's already branch1, don't bother showing it */ | ||||
| 	if (!branch1) | ||||
| 		return; | ||||
| 	memcpy(branch1_sha1, sha1_to_hex_zero(branch1->sha1), 41); | ||||
|  | ||||
| 	printf("0 %06o->%06o %s->%s %s%s\n", | ||||
| 		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); | ||||
| } | ||||
|  | ||||
|  |  | |||
|  | @ -29,12 +29,12 @@ static int verify_packfile(struct packed_git *p) | |||
| 	pack_base = p->pack_base; | ||||
| 	SHA1_Update(&ctx, pack_base, pack_size - 20); | ||||
| 	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)) | ||||
| 		return error("Packfile %s SHA1 mismatch with itself", | ||||
| 			     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 | ||||
| 	 * have verified that nr_objects matches between idx and pack, | ||||
|  |  | |||
|  | @ -1032,12 +1032,6 @@ static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_de | |||
| 		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) | ||||
| 		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 | ||||
| 	 * delete). | ||||
| 	 */ | ||||
| 	size = cur_entry->size; | ||||
| 	max_size = size / 2 - 20; | ||||
| 	if (cur_entry->delta) | ||||
| 		max_size = cur_entry->delta_size-1; | ||||
| 	oldsize = old_entry->size; | ||||
| 	sizediff = oldsize < size ? size - oldsize : 0; | ||||
| 	if (sizediff >= max_size) | ||||
| 		return 0; | ||||
| 	delta_buf = diff_delta(old->data, oldsize, | ||||
|  | @ -1109,6 +1106,9 @@ static void find_deltas(struct object_entry **list, int window, int depth) | |||
| 			 */ | ||||
| 			continue; | ||||
|  | ||||
| 		if (entry->size < 50) | ||||
| 			continue; | ||||
|  | ||||
| 		free(n->data); | ||||
| 		n->entry = entry; | ||||
| 		n->data = read_sha1_file(entry->sha1, type, &size); | ||||
|  | @ -1239,6 +1239,7 @@ int main(int argc, char **argv) | |||
|  | ||||
| 	setup_git_directory(); | ||||
|  | ||||
| 	progress = isatty(2); | ||||
| 	for (i = 1; i < argc; i++) { | ||||
| 		const char *arg = argv[i]; | ||||
|  | ||||
|  | @ -1269,6 +1270,10 @@ int main(int argc, char **argv) | |||
| 					usage(pack_usage); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (!strcmp("--progress", arg)) { | ||||
| 				progress = 1; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (!strcmp("-q", arg)) { | ||||
| 				progress = 0; | ||||
| 				continue; | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
| #include "delta.h" | ||||
|  | ||||
| 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) | ||||
| { | ||||
| 	const unsigned char *data, *top; | ||||
|  |  | |||
							
								
								
									
										4
									
								
								refs.c
								
								
								
								
							
							
						
						
									
										4
									
								
								refs.c
								
								
								
								
							|  | @ -76,8 +76,8 @@ int create_symref(const char *git_HEAD, const char *refs_heads_master) | |||
| 	char ref[1000]; | ||||
| 	int fd, len, written; | ||||
|  | ||||
| #ifdef USE_SYMLINK_HEAD | ||||
| 	if (!only_use_symrefs) { | ||||
| #ifndef NO_SYMLINK_HEAD | ||||
| 	if (prefer_symlink_refs) { | ||||
| 		unlink(git_HEAD); | ||||
| 		if (!symlink(refs_heads_master, git_HEAD)) | ||||
| 			return 0; | ||||
|  |  | |||
|  | @ -2,46 +2,63 @@ | |||
| #include <regex.h> | ||||
|  | ||||
| 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* value = NULL; | ||||
| static regex_t* key_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_not_match = 0; | ||||
| static int seen = 0; | ||||
| 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_) | ||||
| { | ||||
| 	char value[256]; | ||||
| 	const char *vptr = value; | ||||
| 	int dup_error = 0; | ||||
|  | ||||
| 	if (value_ == NULL) | ||||
| 		value_ = ""; | ||||
|  | ||||
| 	if (!strcmp(key_, key) && | ||||
| 			(regexp == NULL || | ||||
| 			 (do_not_match ^ | ||||
| 			  !regexec(regexp, value_, 0, NULL, 0)))) { | ||||
| 		if (do_all) { | ||||
| 			printf("%s\n", value_); | ||||
| 	if (!use_key_regexp && strcmp(key_, key)) | ||||
| 		return 0; | ||||
| 	if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0)) | ||||
| 		return 0; | ||||
| 	if (regexp != NULL && | ||||
| 			 (do_not_match ^ | ||||
| 			  regexec(regexp, value_, 0, NULL, 0))) | ||||
| 		return 0; | ||||
| 		} | ||||
| 		if (seen > 0) { | ||||
| 			fprintf(stderr, "More than one value: %s\n", value); | ||||
| 			free(value); | ||||
| 		} | ||||
|  | ||||
| 		if (type == T_INT) { | ||||
| 			value = malloc(256); | ||||
| 	if (show_keys) | ||||
| 		printf("%s ", key_); | ||||
| 	if (seen && !do_all) | ||||
| 		dup_error = 1; | ||||
| 	if (type == T_INT) | ||||
| 		sprintf(value, "%d", git_config_int(key_, value_)); | ||||
| 		} else if (type == T_BOOL) { | ||||
| 			value = malloc(256); | ||||
| 			sprintf(value, "%s", git_config_bool(key_, value_) | ||||
| 					     ? "true" : "false"); | ||||
| 		} else { | ||||
| 			value = strdup(value_); | ||||
| 		} | ||||
| 	else if (type == T_BOOL) | ||||
| 		vptr = git_config_bool(key_, value_) ? "true" : "false"; | ||||
| 	else | ||||
| 		vptr = value_; | ||||
| 	seen++; | ||||
| 	if (dup_error) { | ||||
| 		error("More than one value for the key %s: %s", | ||||
| 				key_, vptr); | ||||
| 	} | ||||
| 	else | ||||
| 		printf("%s\n", vptr); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | @ -54,6 +71,14 @@ static int get_value(const char* key_, const char* regex_) | |||
| 		key[i] = tolower(key_[i]); | ||||
| 	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_[0] == '!') { | ||||
| 			do_not_match = 1; | ||||
|  | @ -67,11 +92,7 @@ static int get_value(const char* key_, const char* regex_) | |||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	i = git_config(show_config); | ||||
| 	if (value) { | ||||
| 		printf("%s\n", value); | ||||
| 		free(value); | ||||
| 	} | ||||
| 	git_config(show_config); | ||||
| 	free(key); | ||||
| 	if (regexp) { | ||||
| 		regfree(regexp); | ||||
|  | @ -79,9 +100,9 @@ static int get_value(const char* key_, const char* regex_) | |||
| 	} | ||||
|  | ||||
| 	if (do_all) | ||||
| 		return 0; | ||||
| 		return !seen; | ||||
|  | ||||
| 	return seen == 1 ? 0 : 1; | ||||
| 	return (seen == 1) ? 0 : 1; | ||||
| } | ||||
|  | ||||
| int main(int argc, const char **argv) | ||||
|  | @ -93,6 +114,8 @@ int main(int argc, const char **argv) | |||
| 			type = T_INT; | ||||
| 		else if (!strcmp(argv[1], "--bool")) | ||||
| 			type = T_BOOL; | ||||
| 		else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) | ||||
| 			return git_config(show_all_config); | ||||
| 		else | ||||
| 			break; | ||||
| 		argc--; | ||||
|  | @ -112,6 +135,11 @@ int main(int argc, const char **argv) | |||
| 		else if (!strcmp(argv[1], "--get-all")) { | ||||
| 			do_all = 1; | ||||
| 			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 | ||||
|  | ||||
| 			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")) { | ||||
| 			do_all = 1; | ||||
| 			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")) | ||||
|  | ||||
| 			return git_config_set_multivar(argv[2], argv[3], NULL, 1); | ||||
|  |  | |||
|  | @ -169,14 +169,12 @@ int main(int argc, char **argv) | |||
| 	git_config(git_default_config); | ||||
|  | ||||
| 	for (i = 1; i < argc; i++) { | ||||
| 		struct stat st; | ||||
| 		char *arg = argv[i]; | ||||
| 		char *dotdot; | ||||
|  | ||||
| 		if (as_is) { | ||||
| 			if (show_file(arg) && as_is < 2) | ||||
| 				if (lstat(arg, &st) < 0) | ||||
| 					die("'%s': %s", arg, strerror(errno)); | ||||
| 				verify_filename(prefix, arg); | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!strcmp(arg,"-n")) { | ||||
|  | @ -342,8 +340,7 @@ int main(int argc, char **argv) | |||
| 			continue; | ||||
| 		if (verify) | ||||
| 			die("Needed a single revision"); | ||||
| 		if (lstat(arg, &st) < 0) | ||||
| 			die("'%s': %s", arg, strerror(errno)); | ||||
| 		verify_filename(prefix, arg); | ||||
| 	} | ||||
| 	show_default(); | ||||
| 	if (verify && revs_count != 1) | ||||
|  |  | |||
							
								
								
									
										65
									
								
								revision.c
								
								
								
								
							
							
						
						
									
										65
									
								
								revision.c
								
								
								
								
							|  | @ -477,6 +477,36 @@ static void handle_all(struct rev_info *revs, unsigned flags) | |||
| 	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) | ||||
| { | ||||
| 	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); | ||||
| 				continue; | ||||
| 			} | ||||
| 			/* accept -<digit>, like traditilnal "head" */ | ||||
| 			/* accept -<digit>, like traditional "head" */ | ||||
| 			if ((*arg == '-') && isdigit(arg[1])) { | ||||
| 				revs->max_count = atoi(arg + 1); | ||||
| 				continue; | ||||
|  | @ -664,6 +694,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch | |||
| 			} | ||||
| 			if (!strcmp(arg, "-c")) { | ||||
| 				revs->diff = 1; | ||||
| 				revs->dense_combined_merges = 0; | ||||
| 				revs->combine_merges = 1; | ||||
| 				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); | ||||
| 				if (!exclude || !include) | ||||
| 					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, include, next); | ||||
| 				continue; | ||||
| 			} | ||||
| 			*dotdot = '.'; | ||||
| 		} | ||||
| 		dotdot = strstr(arg, "^@"); | ||||
| 		if (dotdot && !dotdot[2]) { | ||||
| 			*dotdot = 0; | ||||
| 			if (add_parents_only(revs, arg, flags)) | ||||
| 				continue; | ||||
| 			*dotdot = '^'; | ||||
| 		} | ||||
| 		local_flags = 0; | ||||
| 		if (*arg == '^') { | ||||
| 			local_flags = UNINTERESTING; | ||||
| 			arg++; | ||||
| 		} | ||||
| 		if (get_sha1(arg, sha1) < 0) { | ||||
| 			struct stat st; | ||||
| 			int j; | ||||
|  | ||||
| 			if (seen_dashdash || local_flags) | ||||
| 				die("bad revision '%s'", arg); | ||||
|  | ||||
| 			/* If we didn't have a "--", all filenames must exist */ | ||||
| 			for (j = i; j < argc; j++) { | ||||
| 				if (lstat(argv[j], &st) < 0) | ||||
| 					die("'%s': %s", argv[j], strerror(errno)); | ||||
| 			} | ||||
| 			/* If we didn't have a "--": | ||||
| 			 * (1) all filenames must exist; | ||||
| 			 * (2) all rev-args must not be interpretable | ||||
| 			 *     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); | ||||
| 			break; | ||||
| 		} | ||||
| 		if (!seen_dashdash) | ||||
| 			verify_non_filename(revs->prefix, arg); | ||||
| 		object = get_reference(revs, arg, sha1, flags ^ local_flags); | ||||
| 		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) { | ||||
| 		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.abbrev = revs->abbrev; | ||||
|  |  | |||
							
								
								
									
										43
									
								
								setup.c
								
								
								
								
							
							
						
						
									
										43
									
								
								setup.c
								
								
								
								
							|  | @ -62,6 +62,49 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg) | |||
| 	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 *entry = *pathspec; | ||||
|  |  | |||
|  | @ -108,9 +108,10 @@ int safe_create_leading_directories(char *path) | |||
|  | ||||
| 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"; | ||||
| 	char *buf = buffer; | ||||
| 	char *buffer = hexbuffer[3 & ++bufno], *buf = buffer; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < 20; i++) { | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ | |||
| #include "refs.h" | ||||
|  | ||||
| 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_alloc = 0; | ||||
|  | @ -527,6 +527,27 @@ static int git_show_branch_config(const char *var, const char *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) | ||||
| { | ||||
| 	struct commit *rev[MAX_REVS], *commit; | ||||
|  | @ -548,6 +569,7 @@ int main(int ac, char **av) | |||
| 	int with_current_branch = 0; | ||||
| 	int head_at = -1; | ||||
| 	int topics = 0; | ||||
| 	int dense = 1; | ||||
|  | ||||
| 	setup_git_directory(); | ||||
| 	git_config(git_show_branch_config); | ||||
|  | @ -590,6 +612,8 @@ int main(int ac, char **av) | |||
| 			lifo = 1; | ||||
| 		else if (!strcmp(arg, "--topics")) | ||||
| 			topics = 1; | ||||
| 		else if (!strcmp(arg, "--sparse")) | ||||
| 			dense = 0; | ||||
| 		else if (!strcmp(arg, "--date-order")) | ||||
| 			lifo = 0; | ||||
| 		else | ||||
|  | @ -732,12 +756,15 @@ int main(int ac, char **av) | |||
| 		shown_merge_point |= is_merge_point; | ||||
|  | ||||
| 		if (1 < num_rev) { | ||||
| 			int is_merge = !!(commit->parents && commit->parents->next); | ||||
| 			int is_merge = !!(commit->parents && | ||||
| 					  commit->parents->next); | ||||
| 			if (topics && | ||||
| 			    !is_merge_point && | ||||
| 			    (this_flag & (1u << REV_SHIFT))) | ||||
| 				continue; | ||||
|  | ||||
| 			if (dense && is_merge && | ||||
| 			    omit_in_dense(commit, rev, num_rev)) | ||||
| 				continue; | ||||
| 			for (i = 0; i < num_rev; i++) { | ||||
| 				int mark; | ||||
| 				if (!(this_flag & (1u << (i + REV_SHIFT)))) | ||||
|  |  | |||
|  | @ -174,6 +174,27 @@ test_expect_success \ | |||
|     'git-ls-tree -r output for a known tree.' \ | ||||
|     '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 | ||||
| test_expect_success \ | ||||
|  | @ -205,4 +226,32 @@ test_expect_success \ | |||
|     'no diff after checkout and git-update-index --refresh.' \ | ||||
|     '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 | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ compare_change () { | |||
| } | ||||
|  | ||||
| check_cache_at () { | ||||
| 	clean_if_empty=`git-diff-files "$1"` | ||||
| 	clean_if_empty=`git-diff-files -- "$1"` | ||||
| 	case "$clean_if_empty" in | ||||
| 	'')  echo "$1: clean" ;; | ||||
| 	?*)  echo "$1: dirty" ;; | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ compare_change () { | |||
| } | ||||
|  | ||||
| check_cache_at () { | ||||
| 	clean_if_empty=`git-diff-files "$1"` | ||||
| 	clean_if_empty=`git-diff-files -- "$1"` | ||||
| 	case "$clean_if_empty" in | ||||
| 	'')  echo "$1: clean" ;; | ||||
| 	?*)  echo "$1: dirty" ;; | ||||
|  |  | |||
|  | @ -247,6 +247,24 @@ EOF | |||
|  | ||||
| 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 | ||||
| [novalue] | ||||
| 	variable | ||||
|  | @ -255,5 +273,41 @@ EOF | |||
| test_expect_success 'get variable with no value' \ | ||||
| 	'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 | ||||
|  | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ cat >expected <<\EOF | |||
| EOF | ||||
| test_expect_success \ | ||||
|     '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' | ||||
|  | ||||
| cat >expected <<\EOF | ||||
|  | @ -36,7 +36,7 @@ cat >expected <<\EOF | |||
| EOF | ||||
| test_expect_success \ | ||||
|     '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' | ||||
|  | ||||
| cat >expected <<\EOF | ||||
|  | @ -44,7 +44,7 @@ cat >expected <<\EOF | |||
| EOF | ||||
| test_expect_success \ | ||||
|     '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' | ||||
|  | ||||
| cat >expected <<\EOF | ||||
|  | @ -52,14 +52,14 @@ cat >expected <<\EOF | |||
| EOF | ||||
| test_expect_success \ | ||||
|     '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' | ||||
|  | ||||
| cat >expected <<\EOF | ||||
| EOF | ||||
| test_expect_success \ | ||||
|     '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' | ||||
|  | ||||
| test_done | ||||
|  |  | |||
							
								
								
									
										170
									
								
								update-index.c
								
								
								
								
							
							
						
						
									
										170
									
								
								update-index.c
								
								
								
								
							|  | @ -6,6 +6,7 @@ | |||
| #include "cache.h" | ||||
| #include "strbuf.h" | ||||
| #include "quote.h" | ||||
| #include "tree-walk.h" | ||||
|  | ||||
| /* | ||||
|  * 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; | ||||
| } | ||||
|  | ||||
| static int chmod_path(int flip, const char *path) | ||||
| static void chmod_path(int flip, const char *path) | ||||
| { | ||||
| 	int pos; | ||||
| 	struct cache_entry *ce; | ||||
|  | @ -336,21 +337,24 @@ static int chmod_path(int flip, const char *path) | |||
|  | ||||
| 	pos = cache_name_pos(path, strlen(path)); | ||||
| 	if (pos < 0) | ||||
| 		return -1; | ||||
| 		goto fail; | ||||
| 	ce = active_cache[pos]; | ||||
| 	mode = ntohl(ce->ce_mode); | ||||
| 	if (!S_ISREG(mode)) | ||||
| 		return -1; | ||||
| 		goto fail; | ||||
| 	switch (flip) { | ||||
| 	case '+': | ||||
| 		ce->ce_mode |= htonl(0111); break; | ||||
| 	case '-': | ||||
| 		ce->ce_mode &= htonl(~0111); break; | ||||
| 	default: | ||||
| 		return -1; | ||||
| 		goto fail; | ||||
| 	} | ||||
| 	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; | ||||
|  | @ -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); | ||||
| 	if (!verify_path(p)) { | ||||
| 		fprintf(stderr, "Ignoring path %s\n", path); | ||||
| 		return; | ||||
| 		goto free_return; | ||||
| 	} | ||||
| 	if (mark_valid_only) { | ||||
| 		if (mark_valid(p)) | ||||
| 			die("Unable to mark file %s", path); | ||||
| 		return; | ||||
| 		goto free_return; | ||||
| 	} | ||||
|  | ||||
| 	if (force_remove) { | ||||
| 		if (remove_file_from_cache(p)) | ||||
| 			die("git-update-index: unable to remove %s", path); | ||||
| 		report("remove '%s'", path); | ||||
| 		return; | ||||
| 		goto free_return; | ||||
| 	} | ||||
| 	if (add_file_to_cache(p)) | ||||
| 		die("Unable to process file %s", path); | ||||
| 	report("add '%s'", path); | ||||
|  free_return: | ||||
| 	if (p != path) | ||||
| 		free((char*)p); | ||||
| } | ||||
|  | ||||
| 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[] = | ||||
| "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) | ||||
| { | ||||
|  | @ -478,6 +607,7 @@ int main(int argc, const char **argv) | |||
| 	int read_from_stdin = 0; | ||||
| 	const char *prefix = setup_git_directory(); | ||||
| 	int prefix_length = prefix ? strlen(prefix) : 0; | ||||
| 	char set_executable_bit = 0; | ||||
|  | ||||
| 	git_config(git_default_config); | ||||
|  | ||||
|  | @ -544,8 +674,7 @@ int main(int argc, const char **argv) | |||
| 			    !strcmp(path, "--chmod=+x")) { | ||||
| 				if (argc <= i+1) | ||||
| 					die("git-update-index: %s <path>", path); | ||||
| 				if (chmod_path(path[8], argv[++i])) | ||||
| 					die("git-update-index: %s cannot chmod %s", path, argv[i]); | ||||
| 				set_executable_bit = path[8]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (!strcmp(path, "--assume-unchanged")) { | ||||
|  | @ -581,6 +710,13 @@ int main(int argc, const char **argv) | |||
| 				read_index_info(line_termination); | ||||
| 				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")) { | ||||
| 				not_new = 1; | ||||
| 				continue; | ||||
|  | @ -594,12 +730,15 @@ int main(int argc, const char **argv) | |||
| 			die("unknown option %s", path); | ||||
| 		} | ||||
| 		update_one(path, prefix, prefix_length); | ||||
| 		if (set_executable_bit) | ||||
| 			chmod_path(set_executable_bit, path); | ||||
| 	} | ||||
| 	if (read_from_stdin) { | ||||
| 		struct strbuf buf; | ||||
| 		strbuf_init(&buf); | ||||
| 		while (1) { | ||||
| 			char *path_name; | ||||
| 			const char *p; | ||||
| 			read_line(&buf, stdin, line_termination); | ||||
| 			if (buf.eof) | ||||
| 				break; | ||||
|  | @ -607,11 +746,18 @@ int main(int argc, const char **argv) | |||
| 				path_name = unquote_c_style(buf.buf, NULL); | ||||
| 			else | ||||
| 				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) | ||||
| 				free(path_name); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  finish: | ||||
| 	if (active_cache_changed) { | ||||
| 		if (write_cache(newfd, active_cache, active_nr) || | ||||
| 		    commit_index_file(&cache_file)) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano