/gitk-git/gitk-wish
/gitweb/GITWEB-BUILD-OPTIONS
/gitweb/gitweb.cgi
-/gitweb/gitweb.min.*
+/gitweb/static/gitweb.min.*
/test-chmtime
/test-ctype
/test-date
Fixes since v1.5.6.2
--------------------
-* Setting core.sharerepository to traditional "true" value was supposed to make
+* Setting core.sharedrepository to traditional "true" value was supposed to make
the repository group writable but should not affect permission for others.
However, since 1.5.6, it was broken to drop permission for others when umask is
022, making the repository unreadable by others.
* Many commands did not use the correct working tree location when used
with GIT_WORK_TREE environment settings.
-* Some systems needs to use compatibility fnmach and regex libraries
+* Some systems need to use compatibility fnmatch and regex libraries
independent from each other; the compat/ area has been reorganized to
allow this.
been deprecated.
* "git fetch" and "git clone" had an extra sanity check to verify the
- presense of the corresponding *.pack file before downloading *.idx
+ presence of the corresponding *.pack file before downloading *.idx
file by issuing a HEAD request. Github server however sometimes
gave 500 (Internal server error) response to HEAD even if a GET
request for *.pack file to the same URL would have succeeded, and broke
future versions, but not in this release,
* "git merge -m <message> <branch>..." added the standard merge message
- on its own after user-supplied message, which should have overrided the
+ on its own after user-supplied message, which should have overridden the
standard one.
Other minor documentation updates are included.
an older version of git should just ignore them. Instead we diagnosed
it as an error.
-* With help.autocorrect set to non-zero value, the logic to guess typoes
+* With help.autocorrect set to non-zero value, the logic to guess typos
in the subcommand name misfired and ran a random nonsense command.
* If a command is run with an absolute path as a pathspec inside a bare
the new version of git. When we switched from "git-foo" to "git foo" in
1.6.0, even though the change had been advertised and the transition
guide had been provided for a very long time, the users procrastinated
-during the entire transtion period, and ended up panicking on the day
+during the entire transition period, and ended up panicking on the day
their sysadmins updated their git installation. We are trying to avoid
repeating that unpleasantness in the 1.7.0 release.
* "git diff" traditionally treated various "ignore whitespace" options
only as a way to filter the patch output. "git diff --exit-code -b"
exited with non-zero status even if all changes were about changing the
- ammount of whitespace and nothing else. and "git diff -b" showed the
+ amount of whitespace and nothing else. and "git diff -b" showed the
"diff --git" header line for such a change without patch text.
In 1.7.0, the "ignore whitespaces" will affect the semantics of the
--- /dev/null
+Git v1.7.0.7 Release Notes
+==========================
+
+Fixes since v1.7.0.6
+--------------------
+
+ * "make NO_CURL=NoThanks install" was broken.
+
+ * An overlong line after ".gitdir: " in a git file caused out of bounds
+ access to an array on the stack.
+
+ * "git config --path conf.var" to attempt to expand a variable conf.var
+ that uses "~/" short-hand segfaulted when $HOME environment variable
+ was not set.
+
+And other minor fixes and documentation updates.
the branch is fully merged to its upstream branch if it is not merged
to the current branch. It now deletes it in such a case.
- * "fiter-branch" command incorrectly said --prune-empty and --filter-commit
+ * "filter-branch" command incorrectly said --prune-empty and --filter-commit
were incompatible; the latter should be read as --commit-filter.
* When using "git status" or asking "git diff" to compare the work tree
* "git rev-parse --parseopt --stop-at-non-option" did not stop at non option
when --keep-dashdash was in effect.
+
+ * An overlong line after ".gitdir: " in a git file caused out of bounds
+ access to an array on the stack.
+
+ * "git config --path conf.var" to attempt to expand a variable conf.var
+ that uses "~/" short-hand segfaulted when $HOME environment variable
+ was not set.
+
+And other minor fixes and documentation updates.
--- /dev/null
+Git v1.7.2.1 Release Notes
+==========================
+
+Fixes since v1.7.2
+------------------
+
+ * "git instaweb" wasn't useful when your Apache was installed under a
+ name other than apache2 (e.g. "httpd").
+
+ * Similarly, "git web--browse" (invoked by "git help -w") learned that
+ chrome browser is sometimes called google-chrome.
+
+ * An overlong line after ".gitdir: " in a git file caused out of bounds
+ access to an array on the stack.
+
+ * "git config --path conf.var" to attempt to expand a variable conf.var
+ that uses "~/" short-hand segfaulted when $HOME environment variable
+ was not set.
+
+ * Documentation on Cygwin failed to build.
+
+ * The error message from "git pull blarg" when 'blarg' is an unknown
+ remote name has been improved.
+
+And other minor fixes and documentation updates.
--- /dev/null
+Git v1.7.2.2 Release Notes
+==========================
+
+Fixes since v1.7.2.1
+--------------------
+
+ * Object transfer over smart http transport deadlocked the client when
+ the remote HTTP server returned a failure, instead of erroring it out.
+
+ * git-gui honors custom textconv filters when showing diff and blame;
+
+ * git diff --relative=subdir (without the necessary trailing /) did not
+ work well;
+
+ * "git diff-files -p --submodule" was recently broken;
+
+ * "git checkout -b n ':/token'" did not work;
+
+ * "git index-pack" (hence "git fetch/clone/pull/push") enabled the object
+ replacement machinery by mistake (it never should have);
+
+And other minor fixes and documentation updates.
when writing commit messages. Default: true.
commitBeforeMerge::
Advice shown when linkgit:git-merge[1] refuses to
- merge to avoid overwritting local changes.
+ merge to avoid overwriting local changes.
Default: true.
resolveConflict::
Advices shown by various commands when conflicts
core.deltaBaseCacheLimit::
Maximum number of bytes to reserve for caching base objects
- that multiple deltafied objects reference. By storing the
+ that may be referenced by multiple deltified objects. By storing the
entire decompressed base objects in a cache Git is able
to avoid unpacking and decompressing frequently used base
objects multiple times.
am.keepcr::
If true, git-am will call git-mailsplit for patches in mbox format
with parameter '--keep-cr'. In this case git-mailsplit will
- not remove `\r` from lines ending with `\r\n`. Can be overrriden
+ not remove `\r` from lines ending with `\r\n`. Can be overridden
by giving '--no-keep-cr' from the command line.
See linkgit:git-am[1], linkgit:git-mailsplit[1].
If true, the server will look up the end-of-line conversion
attributes for files to determine the '-k' modes to use. If
the attributes force git to treat a file as text,
- the '-k' mode will be left blank so cvs clients will
+ the '-k' mode will be left blank so CVS clients will
treat it as text. If they suppress text conversion, the file
will be set with '-kb' mode, which suppresses any newline munging
the client might otherwise do. If the attributes do not allow
be bound to the local IP (127.0.0.1).
instaweb.modulepath::
- The module path for an apache httpd used by linkgit:git-instaweb[1].
+ The default module path for linkgit:git-instaweb[1] to use
+ instead of /usr/lib/apache2/modules. Only used if httpd
+ is Apache.
instaweb.port::
The port number to bind the gitweb httpd to. See
If set to true, git-receive-pack will deny a ref update that deletes
the ref. Use this to prevent such a ref deletion via a push.
+receive.denyDeleteCurrent::
+ If set to true, git-receive-pack will deny a ref update that
+ deletes the currently checked out branch of a non-bare repository.
+
receive.denyCurrentBranch::
If set to true or "refuse", git-receive-pack will deny a ref update
to the currently checked out branch of a non-bare repository.
the diff-patch output format. Non default number of
digits can be specified with `--abbrev=<n>`.
--B::
- Break complete rewrite changes into pairs of delete and create.
-
--M::
+-B[<n>][/<m>]::
+ Break complete rewrite changes into pairs of delete and
+ create. This serves two purposes:
++
+It affects the way a change that amounts to a total rewrite of a file
+not as a series of deletion and insertion mixed together with a very
+few lines that happen to match textually as the context, but as a
+single deletion of everything old followed by a single insertion of
+everything new, and the number `m` controls this aspect of the -B
+option (defaults to 60%). `-B/70%` specifies that less than 30% of the
+original should remain in the result for git to consider it a total
+rewrite (i.e. otherwise the resulting patch will be a series of
+deletion and insertion mixed together with context lines).
++
+When used with -M, a totally-rewritten file is also considered as the
+source of a rename (usually -M only considers a file that disappeared
+as the source of a rename), and the number `n` controls this aspect of
+the -B option (defaults to 50%). `-B20%` specifies that a change with
+addition and deletion compared to 20% or more of the file's size are
+eligible for being picked up as a possible source of a rename to
+another file.
+
+-M[<n>]::
ifndef::git-log[]
Detect renames.
endif::git-log[]
For following files across renames while traversing history, see
`--follow`.
endif::git-log[]
+ If `n` is specified, it is a is a threshold on the similarity
+ index (i.e. amount of addition/deletions compared to the
+ file's size). For example, `-M90%` means git should consider a
+ delete/add pair to be a rename if more than 90% of the file
+ hasn't changed.
--C::
+-C[<n>]::
Detect copies as well as renames. See also `--find-copies-harder`.
+ If `n` is specified, it has the same meaning as for `-M<n>`.
ifndef::git-format-patch[]
--diff-filter=[ACDMRTUXB*]::
Without these options, the command applies the patch only to files,
and does not require them to be in a git repository.
+This command applies the patch but does not create a commit. Use
+linkgit:git-am[1] to create commits from patches generated by
+linkgit:git-format-patch[1] and/or received by email.
+
OPTIONS
-------
<patch>...::
are ignored and only the absence or presence of the corresponding
subdirectory is checked and (if possible) updated.
+
+SEE ALSO
+--------
+linkgit:git-am[1].
+
+
Author
------
Written by Linus Torvalds <torvalds@osdl.org>
The smaller the changes in your commit, the most effective "git
bisect" will be. And you will probably need "git bisect" less in the
first place, as small changes are easier to review even if they are
-only reviewed by the commiter.
+only reviewed by the committer.
Another good idea is to have good commit messages. They can be very
helpful to understand why some changes were made.
Usually recording a commit that has the exact same tree as its
sole parent commit is a mistake, and the command prevents you
from making such a commit. This option bypasses the safety, and
- is primarily for use by foreign scm interface scripts.
+ is primarily for use by foreign SCM interface scripts.
--allow-empty-message::
Like --allow-empty this command is primarily for use by foreign
- scm interface scripts. It allows you to create a commit with an
+ SCM interface scripts. It allows you to create a commit with an
empty commit message without using plumbing commands like
linkgit:git-commit-tree[1].
------
Problems related to timestamps:
- * If timestamps of commits in the cvs repository are not stable enough
+ * If timestamps of commits in the CVS repository are not stable enough
to be used for ordering commits changes may show up in the wrong
order.
* If any files were ever "cvs import"ed more than once (e.g., import of
* Branches on which no commits have been made are not imported.
* All files from the branching point are added to a branch even if
- never added in cvs.
+ never added in CVS.
* This applies to files added to the source branch *after* a daughter
branch was created: if previously no commit was made on the daughter
branch they will erroneously be added to the daughter branch in git.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
By default the server leaves the '-k' mode blank for all files,
-which causes the cvs client to treat them as a text files, subject
-to crlf conversion on some platforms.
+which causes the CVS client to treat them as a text files, subject
+to end-of-line conversion on some platforms.
You can make the server use the end-of-line conversion attributes to
set the '-k' modes for files by setting the `gitcvs.usecrlfattr`
--no-filters::
Hash the contents as is, ignoring any input filter that would
- have been chosen by the attributes mechanism, including crlf
+ have been chosen by the attributes mechanism, including the end-of-line
conversion. If the file is read from standard input then this
is always implied, unless the --path option is given.
paths. With this, the full diff is shown for commits that touch
the specified paths; this means that "<path>..." limits only
commits, and doesn't limit diff for those commits.
++
+Note that this affects all diff-based output types, e.g. those
+produced by --stat etc.
--log-size::
Before the log message print out its size in bytes. Intended
with `-s` or `-u` options does not make any sense.
-t::
- Identify the file status with the following tags (followed by
- a space) at the start of each line:
+ This feature is semi-deprecated. For scripting purpose,
+ linkgit:git-status[1] `--porcelain` and
+ linkgit:git-diff-files[1] `--name-status` are almost always
+ superior alternatives, and users should look at
+ linkgit:git-status[1] `--short` or linkgit:git-diff[1]
+ `--name-status` for more user-friendly alternatives.
++
+This option identifies the file status with the following tags (followed by
+a space) at the start of each line:
+
H:: cached
S:: skip-worktree
M:: unmerged
is taken to be in `refs/notes/` if it is not qualified.
-n::
+--dry-run::
Do not remove anything; just report the object names whose notes
would be removed.
-v::
+--verbose::
Report all object names whose notes are removed.
-------
-n::
+--dry-run::
Do not remove anything; just report what it would
remove.
-v::
+--verbose::
Report all removed objects.
\--::
SYNOPSIS
--------
-'git pull' <options> <repository> <refspec>...
+'git pull' [options] [<repository> [<refspec>...]]
DESCRIPTION
-----------
-Runs 'git fetch' with the given parameters, and calls 'git merge'
-to merge the retrieved head(s) into the current branch.
-With `--rebase`, calls 'git rebase' instead of 'git merge'.
-Note that you can use `.` (current directory) as the
-<repository> to pull from the local repository -- this is useful
-when merging local branches into the current branch.
+Incorporates changes from a remote repository into the current
+branch. In its default mode, `git pull` is shorthand for
+`git fetch` followed by `git merge FETCH_HEAD`.
-Also note that options meant for 'git pull' itself and underlying
-'git merge' must be given before the options meant for 'git fetch'.
+More precisely, 'git pull' runs 'git fetch' with the given
+parameters and calls 'git merge' to merge the retrieved branch
+heads into the current branch.
+With `--rebase`, it runs 'git rebase' instead of 'git merge'.
-*Warning*: Running 'git pull' (actually, the underlying 'git merge')
+<repository> should be the name of a remote repository as
+passed to linkgit:git-fetch[1]. <refspec> can name an
+arbitrary remote ref (for example, the name of a tag) or even
+a collection of refs with corresponding remote tracking branches
+(e.g., refs/heads/*:refs/remotes/origin/*), but usually it is
+the name of a branch in the remote repository.
+
+Default values for <repository> and <branch> are read from the
+"remote" and "merge" configuration for the current branch
+as set by linkgit:git-branch[1] `--track`.
+
+Assume the following history exists and the current branch is
+"`master`":
+
+------------
+ A---B---C master on origin
+ /
+ D---E---F---G master
+------------
+
+Then "`git pull`" will fetch and replay the changes from the remote
+`master` branch since it diverged from the local `master` (i.e., `E`)
+until its current commit (`C`) on top of `master` and record the
+result in a new commit along with the names of the two parent commits
+and a log message from the user describing the changes.
+
+------------
+ A---B---C remotes/origin/master
+ / \
+ D---E---F---G---H master
+------------
+
+See linkgit:git-merge[1] for details, including how conflicts
+are presented and handled.
+
+In git 1.7.0 or later, to cancel a conflicting merge, use
+`git reset --merge`. *Warning*: In older versions of git, running 'git pull'
with uncommitted changes is discouraged: while possible, it leaves you
-in a state that is hard to back out of in the case of a conflict.
+in a state that may be hard to back out of in the case of a conflict.
+
+If any of the remote changes overlap with local uncommitted changes,
+the merge will be automatically cancelled and the work tree untouched.
+It is generally best to get any local changes in working order before
+pulling or stash them away with linkgit:git-stash[1].
OPTIONS
-------
+Options meant for 'git pull' itself and the underlying 'git merge'
+must be given before the options meant for 'git fetch'.
+
-q::
--quiet::
This is passed to both underlying git-fetch to squelch reporting of
For a successfully pushed ref, the summary shows the old and new
values of the ref in a form suitable for using as an argument to
`git log` (this is `<old>..<new>` in most cases, and
- `<old>...<new>` for forced non-fast-forward updates). For a
- failed update, more details are given for the failure.
- The string `rejected` indicates that git did not try to send the
- ref at all (typically because it is not a fast-forward). The
- string `remote rejected` indicates that the remote end refused
- the update; this rejection is typically caused by a hook on the
- remote side. The string `remote failure` indicates that the
- remote end did not report the successful update of the ref
- (perhaps because of a temporary error on the remote side, a
- break in the network connection, or other transient error).
+ `<old>...<new>` for forced non-fast-forward updates).
++
+For a failed update, more details are given:
++
+--
+rejected::
+ Git did not try to send the ref at all, typically because it
+ is not a fast-forward and you did not force the update.
+
+remote rejected::
+ The remote end refused the update. Usually caused by a hook
+ on the remote side, or because the remote repository has one
+ of the following safety options in effect:
+ `receive.denyCurrentBranch` (for pushes to the checked out
+ branch), `receive.denyNonFastForwards` (for forced
+ non-fast-forward updates), `receive.denyDeletes` or
+ `receive.denyDeleteCurrent`. See linkgit:git-config[1].
+
+remote failure::
+ The remote end did not report the successful update of the ref,
+ perhaps because of a temporary error on the remote side, a
+ break in the network connection, or other transient error.
+--
from::
The name of the local ref being pushed, minus its
support.
+BUGS
+----
+In order to match a directory with $GIT_DIR/info/sparse-checkout,
+trailing slash must be used. The form without trailing slash, while
+works with .gitignore, does not work with sparse checkout.
+
+
SEE ALSO
--------
linkgit:git-write-tree[1]; linkgit:git-ls-files[1];
SYNOPSIS
--------
-'git request-pull' <start> <url> [<end>]
+'git request-pull' [-p] <start> <url> [<end>]
DESCRIPTION
-----------
OPTIONS
-------
+-p::
+ Show patch text
+
<start>::
Commit to start at.
SYNOPSIS
--------
[verse]
-'git reset' [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]
'git reset' [-q] [<commit>] [--] <paths>...
'git reset' --patch [<commit>] [--] [<paths>...]
+'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]
DESCRIPTION
-----------
-Sets the current head to the specified commit and optionally resets the
-index and working tree to match.
-
-This command is useful if you notice some small error in a recent
-commit (or set of commits) and want to redo that part without showing
-the undo in the history.
-
-If you want to undo a commit other than the latest on a branch,
-linkgit:git-revert[1] is your friend.
-
-The second and third forms with 'paths' and/or --patch are used to
-revert selected paths in the index from a given commit, without moving
-HEAD.
-
+In the first and second form, copy entries from <commit> to the index.
+In the third form, set the current branch to <commit>, optionally
+modifying index and worktree to match. The <commit> defaults to HEAD
+in all forms.
+
+'git reset' [-q] [<commit>] [--] <paths>...::
+ This form resets the index entries for all <paths> to their
+ state at the <commit>. (It does not affect the worktree, nor
+ the current branch.)
++
+This means that `git reset <paths>` is the opposite of `git add
+<paths>`.
-OPTIONS
--------
---mixed::
- Resets the index but not the working tree (i.e., the changed files
- are preserved but not marked for commit) and reports what has not
- been updated. This is the default action.
+'git reset' --patch|-p [<commit>] [--] [<paths>...]::
+ Interactively select hunks in the difference between the index
+ and <commit> (defaults to HEAD). The chosen hunks are applied
+ in reverse to the index.
++
+This means that `git reset -p` is the opposite of `git add -p` (see
+linkgit:git-add[1]).
+'git reset' [--<mode>] [<commit>]::
+ This form points the current branch to <commit> and then
+ updates index and working tree according to <mode>, which must
+ be one of the following:
++
+--
--soft::
Does not touch the index file nor the working tree at all, but
requires them to be in a good order. This leaves all your changed
files "Changes to be committed", as 'git status' would
put it.
+--mixed::
+ Resets the index but not the working tree (i.e., the changed files
+ are preserved but not marked for commit) and reports what has not
+ been updated. This is the default action.
+
--hard::
Matches the working tree and index to that of the tree being
switched to. Any changes to tracked files in the working tree
the given commit. If a file that is different between the
current commit and the given commit has local changes, reset
is aborted.
+--
--p::
---patch::
- Interactively select hunks in the difference between the index
- and <commit> (defaults to HEAD). The chosen hunks are applied
- in reverse to the index.
-+
-This means that `git reset -p` is the opposite of `git add -p` (see
-linkgit:git-add[1]).
+If you want to undo a commit other than the latest on a branch,
+linkgit:git-revert[1] is your friend.
+
+
+OPTIONS
+-------
-q::
--quiet::
Be quiet, only report errors.
-<commit>::
- Commit to make the current HEAD. If not given defaults to HEAD.
-
-DISCUSSION
-----------
-The tables below show what happens when running:
-
-----------
-git reset --option target
-----------
-
-to reset the HEAD to another commit (`target`) with the different
-reset options depending on the state of the files.
-
-In these tables, A, B, C and D are some different states of a
-file. For example, the first line of the first table means that if a
-file is in state A in the working tree, in state B in the index, in
-state C in HEAD and in state D in the target, then "git reset --soft
-target" will put the file in state A in the working tree, in state B
-in the index and in state D in HEAD.
-
- working index HEAD target working index HEAD
- ----------------------------------------------------
- A B C D --soft A B D
- --mixed A D D
- --hard D D D
- --merge (disallowed)
- --keep (disallowed)
-
- working index HEAD target working index HEAD
- ----------------------------------------------------
- A B C C --soft A B C
- --mixed A C C
- --hard C C C
- --merge (disallowed)
- --keep A C C
-
- working index HEAD target working index HEAD
- ----------------------------------------------------
- B B C D --soft B B D
- --mixed B D D
- --hard D D D
- --merge D D D
- --keep (disallowed)
-
- working index HEAD target working index HEAD
- ----------------------------------------------------
- B B C C --soft B B C
- --mixed B C C
- --hard C C C
- --merge C C C
- --keep B C C
-
- working index HEAD target working index HEAD
- ----------------------------------------------------
- B C C D --soft B C D
- --mixed B D D
- --hard D D D
- --merge (disallowed)
- --keep (disallowed)
-
- working index HEAD target working index HEAD
- ----------------------------------------------------
- B C C C --soft B C C
- --mixed B C C
- --hard C C C
- --merge B C C
- --keep B C C
-
-"reset --merge" is meant to be used when resetting out of a conflicted
-merge. Any mergy operation guarantees that the work tree file that is
-involved in the merge does not have local change wrt the index before
-it starts, and that it writes the result out to the work tree. So if
-we see some difference between the index and the target and also
-between the index and the work tree, then it means that we are not
-resetting out from a state that a mergy operation left after failing
-with a conflict. That is why we disallow --merge option in this case.
-
-"reset --keep" is meant to be used when removing some of the last
-commits in the current branch while keeping changes in the working
-tree. If there could be conflicts between the changes in the commit we
-want to remove and the changes in the working tree we want to keep,
-the reset is disallowed. That's why it is disallowed if there are both
-changes between the working tree and HEAD, and between HEAD and the
-target. To be safe, it is also disallowed when there are unmerged
-entries.
-
-The following tables show what happens when there are unmerged
-entries:
-
- working index HEAD target working index HEAD
- ----------------------------------------------------
- X U A B --soft (disallowed)
- --mixed X B B
- --hard B B B
- --merge B B B
- --keep (disallowed)
-
- working index HEAD target working index HEAD
- ----------------------------------------------------
- X U A A --soft (disallowed)
- --mixed X A A
- --hard A A A
- --merge A A A
- --keep (disallowed)
-
-X means any state and U means an unmerged index.
-
-Examples
+EXAMPLES
--------
+Undo add::
++
+------------
+$ edit <1>
+$ git add frotz.c filfre.c
+$ mailx <2>
+$ git reset <3>
+$ git pull git://info.example.com/ nitfol <4>
+------------
++
+<1> You are happily working on something, and find the changes
+in these files are in good order. You do not want to see them
+when you run "git diff", because you plan to work on other files
+and changes with these files are distracting.
+<2> Somebody asks you to pull, and the changes sounds worthy of merging.
+<3> However, you already dirtied the index (i.e. your index does
+not match the HEAD commit). But you know the pull you are going
+to make does not affect frotz.c nor filfre.c, so you revert the
+index changes for these two files. Your changes in working tree
+remain there.
+<4> Then you can pull and merge, leaving frotz.c and filfre.c
+changes still in the working tree.
+
Undo a commit and redo::
+
------------
+
See also the --amend option to linkgit:git-commit[1].
-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. (See the
-"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for
-the implications of doing so.)
-
Undo a commit, making it a topic branch::
+
------------
<2> Rewind the master branch to get rid of those three commits.
<3> Switch to "topic/wip" branch and keep working.
-Undo add::
+Undo commits permanently::
+
------------
-$ edit <1>
-$ git add frotz.c filfre.c
-$ mailx <2>
-$ git reset <3>
-$ git pull git://info.example.com/ nitfol <4>
+$ git commit ...
+$ git reset --hard HEAD~3 <1>
------------
+
-<1> You are happily working on something, and find the changes
-in these files are in good order. You do not want to see them
-when you run "git diff", because you plan to work on other files
-and changes with these files are distracting.
-<2> Somebody asks you to pull, and the changes sounds worthy of merging.
-<3> However, you already dirtied the index (i.e. your index does
-not match the HEAD commit). But you know the pull you are going
-to make does not affect frotz.c nor filfre.c, so you revert the
-index changes for these two files. Your changes in working tree
-remain there.
-<4> Then you can pull and merge, leaving frotz.c and filfre.c
-changes still in the working tree.
+<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. (See the
+"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for
+the implications of doing so.)
Undo a merge or pull::
+
Suppose you are working on something and you commit it, and then you
continue working a bit more, but now you think that what you have in
your working tree should be in another branch that has nothing to do
-with what you commited previously. You can start a new branch and
+with what you committed previously. You can start a new branch and
reset it while keeping the changes in your work tree.
+
------------
<3> But you can use "reset --keep" to remove the unwanted commit after
you switched to "branch2".
+
+DISCUSSION
+----------
+
+The tables below show what happens when running:
+
+----------
+git reset --option target
+----------
+
+to reset the HEAD to another commit (`target`) with the different
+reset options depending on the state of the files.
+
+In these tables, A, B, C and D are some different states of a
+file. For example, the first line of the first table means that if a
+file is in state A in the working tree, in state B in the index, in
+state C in HEAD and in state D in the target, then "git reset --soft
+target" will put the file in state A in the working tree, in state B
+in the index and in state D in HEAD.
+
+ working index HEAD target working index HEAD
+ ----------------------------------------------------
+ A B C D --soft A B D
+ --mixed A D D
+ --hard D D D
+ --merge (disallowed)
+ --keep (disallowed)
+
+ working index HEAD target working index HEAD
+ ----------------------------------------------------
+ A B C C --soft A B C
+ --mixed A C C
+ --hard C C C
+ --merge (disallowed)
+ --keep A C C
+
+ working index HEAD target working index HEAD
+ ----------------------------------------------------
+ B B C D --soft B B D
+ --mixed B D D
+ --hard D D D
+ --merge D D D
+ --keep (disallowed)
+
+ working index HEAD target working index HEAD
+ ----------------------------------------------------
+ B B C C --soft B B C
+ --mixed B C C
+ --hard C C C
+ --merge C C C
+ --keep B C C
+
+ working index HEAD target working index HEAD
+ ----------------------------------------------------
+ B C C D --soft B C D
+ --mixed B D D
+ --hard D D D
+ --merge (disallowed)
+ --keep (disallowed)
+
+ working index HEAD target working index HEAD
+ ----------------------------------------------------
+ B C C C --soft B C C
+ --mixed B C C
+ --hard C C C
+ --merge B C C
+ --keep B C C
+
+"reset --merge" is meant to be used when resetting out of a conflicted
+merge. Any mergy operation guarantees that the work tree file that is
+involved in the merge does not have local change wrt the index before
+it starts, and that it writes the result out to the work tree. So if
+we see some difference between the index and the target and also
+between the index and the work tree, then it means that we are not
+resetting out from a state that a mergy operation left after failing
+with a conflict. That is why we disallow --merge option in this case.
+
+"reset --keep" is meant to be used when removing some of the last
+commits in the current branch while keeping changes in the working
+tree. If there could be conflicts between the changes in the commit we
+want to remove and the changes in the working tree we want to keep,
+the reset is disallowed. That's why it is disallowed if there are both
+changes between the working tree and HEAD, and between HEAD and the
+target. To be safe, it is also disallowed when there are unmerged
+entries.
+
+The following tables show what happens when there are unmerged
+entries:
+
+ working index HEAD target working index HEAD
+ ----------------------------------------------------
+ X U A B --soft (disallowed)
+ --mixed X B B
+ --hard B B B
+ --merge B B B
+ --keep (disallowed)
+
+ working index HEAD target working index HEAD
+ ----------------------------------------------------
+ X U A A --soft (disallowed)
+ --mixed X A A
+ --hard A A A
+ --merge A A A
+ --keep (disallowed)
+
+X means any state and U means an unmerged index.
+
+
Author
------
Written by Junio C Hamano <gitster@pobox.com> and Linus Torvalds <torvalds@osdl.org>
(e.g. splits single switches aggregate values), a bit like `getopt(1)` does.
It takes on the standard input the specification of the options to parse and
-understand, and echoes on the standard output a line suitable for `sh(1)` `eval`
+understand, and echoes on the standard output a string suitable for `sh(1)` `eval`
to replace the arguments with normalized ones. In case of error, it outputs
usage on the standard error stream, and exits with code 129.
+Note: Make sure you quote the result when passing it to `eval`. See
+below for an example.
+
Input Format
~~~~~~~~~~~~
An option group Header
C? option C with an optional argument"
-eval `echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?`
+eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
------------
SQ-QUOTE
to get a listing of all tags together with what they dereference.
+FILES
+-----
+`.git/refs/*`, `.git/packed-refs`
+
SEE ALSO
--------
-linkgit:git-ls-remote[1]
+linkgit:git-ls-remote[1],
+linkgit:git-update-ref[1],
+linkgit:gitrepository-layout[5]
AUTHORS
-------
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.7.2/git.html[documentation for release 1.7.2]
+* link:v1.7.2.2/git.html[documentation for release 1.7.2.2]
* release notes for
+ link:RelNotes-1.7.2.2.txt[1.7.2.2],
+ link:RelNotes-1.7.2.1.txt[1.7.2.1],
link:RelNotes-1.7.2.txt[1.7.2].
-* link:v1.7.1.1/git.html[documentation for release 1.7.1.1]
+* link:v1.7.1.2/git.html[documentation for release 1.7.1.2]
* release notes for
+ link:RelNotes-1.7.1.2.txt[1.7.1.2],
link:RelNotes-1.7.1.1.txt[1.7.1.1],
link:RelNotes-1.7.1.txt[1.7.1].
-* link:v1.7.0.6/git.html[documentation for release 1.7.0.6]
+* link:v1.7.0.7/git.html[documentation for release 1.7.0.7]
* release notes for
+ link:RelNotes-1.7.0.7.txt[1.7.0.7],
link:RelNotes-1.7.0.6.txt[1.7.0.6],
link:RelNotes-1.7.0.5.txt[1.7.0.5],
link:RelNotes-1.7.0.4.txt[1.7.0.4],
<david@dgreaves.com>, and later enhanced greatly by the
contributors on the git-list <git@vger.kernel.org>.
+Reporting Bugs
+--------------
+
+Report bugs to the Git mailing list <git@vger.kernel.org> where the
+development and maintenance is primarily done. You do not have to be
+subscribed to the list to send a message there.
+
SEE ALSO
--------
linkgit:gittutorial[7], linkgit:gittutorial-2[7],
directory for a repository associated with your working tree, or
`<project>.git` directory for a public 'bare' repository. It is
also possible to have a working tree where `.git` is a plain
-ascii file containing `gitdir: <path>`, i.e. the path to the
+ASCII file containing `gitdir: <path>`, i.e. the path to the
real git repository).
objects::
A---B---C
But if you don't actually need to change commit A, then you need some way to
-recreate it as a new commit with the same changes in it. The rebase commmand's
+recreate it as a new commit with the same changes in it. The rebase command's
--no-ff option provides a way to do this:
$ git rebase [-i] --no-ff P
--pretty[='<format>']::
---format[='<format>']::
+--format='<format>'::
Pretty-print the contents of the commit logs in a given format,
where '<format>' can be one of 'oneline', 'short', 'medium',
- git://host.xz{startsb}:port{endsb}/~{startsb}user{endsb}/path/to/repo.git/
- {startsb}user@{endsb}host.xz:/~{startsb}user{endsb}/path/to/repo.git/
-For local respositories, also supported by git natively, the following
+For local repositories, also supported by git natively, the following
syntaxes may be used:
- /path/to/repo.git/
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.2
+DEF_VER=v1.7.2.2
LF='
'
It has been reported that docbook-xsl version 1.72 and 1.73 are
buggy; 1.72 misformats manual pages for callouts, and 1.73 needs
the patch in contrib/patches/docbook-xsl-manpages-charmap.patch
+
+ Users attempting to build the documentation on Cygwin may need to ensure
+ that the /etc/xml/catalog file looks something like this:
+
+ <?xml version="1.0"?>
+ <!DOCTYPE catalog PUBLIC
+ "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN"
+ "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd"
+ >
+ <catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <rewriteURI
+ uriStartString = "http://docbook.sourceforge.net/release/xsl/current"
+ rewritePrefix = "/usr/share/sgml/docbook/xsl-stylesheets"
+ />
+ <rewriteURI
+ uriStartString="http://www.oasis-open.org/docbook/xml/4.5"
+ rewritePrefix="/usr/share/sgml/docbook/xml-dtd-4.5"
+ />
+ </catalog>
+
+ This can be achieved with the following two xmlcatalog commands:
+
+ xmlcatalog --noout \
+ --add rewriteURI \
+ http://docbook.sourceforge.net/release/xsl/current \
+ /usr/share/sgml/docbook/xsl-stylesheets \
+ /etc/xml/catalog
+
+ xmlcatalog --noout \
+ --add rewriteURI \
+ http://www.oasis-open.org/docbook/xml/4.5/xsl/current \
+ /usr/share/sgml/docbook/xml-dtd-4.5 \
+ /etc/xml/catalog
builtin/commit.o builtin/revert.o wt-status.o: wt-status.h
builtin/tar-tree.o archive-tar.o: tar.h
builtin/pack-objects.o: thread-utils.h
+connect.o transport.o http-backend.o: url.h
http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h
-http.o http-walker.o http-push.o remote-curl.o: http.h
+http.o http-walker.o http-push.o http-fetch.o remote-curl.o: http.h
xdiff-interface.o $(XDIFF_OBJS): \
xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
{ test "$$bindir/" = "$$execdir/" || \
- { $(RM) "$$execdir/git$X" && \
+ for p in git$X $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \
+ $(RM) "$$execdir/$$p" && \
test -z "$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
- ln "$$bindir/git$X" "$$execdir/git$X" 2>/dev/null || \
- cp "$$bindir/git$X" "$$execdir/git$X"; } ; } && \
+ ln "$$bindir/$$p" "$$execdir/$$p" 2>/dev/null || \
+ cp "$$bindir/$$p" "$$execdir/$$p" || exit; \
+ done; \
+ } && \
+ for p in $(filter $(install_bindir_programs),$(BUILT_INS)); do \
+ $(RM) "$$bindir/$$p" && \
+ ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
+ ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
+ cp "$$bindir/git$X" "$$bindir/$$p" || exit; \
+ done && \
for p in $(BUILT_INS); do \
$(RM) "$$execdir/$$p" && \
ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
documented,gitglossary | \
documented,githooks | \
documented,gitrepository-layout | \
+ documented,gitrevisions | \
documented,gittutorial | \
documented,gittutorial-2 | \
documented,git-bisect-lk2009 | \
-Documentation/RelNotes-1.7.2.txt
\ No newline at end of file
+Documentation/RelNotes-1.7.2.2.txt
\ No newline at end of file
struct strbuf fmt = STRBUF_INIT;
struct pretty_print_context ctx = {0};
ctx.date_mode = DATE_NORMAL;
+ ctx.abbrev = DEFAULT_ABBREV;
if (src == buf->buf)
to_free = strbuf_detach(buf, NULL);
#define say1(a,b) fprintf(stderr, a, b)
#define say2(a,b,c) fprintf(stderr, a, b, c)
#else
-#define say(a) do {} while(0)
-#define say1(a,b) do {} while(0)
-#define say2(a,b,c) do {} while(0)
+#define say(a) do { /* nothing */ } while (0)
+#define say1(a,b) do { /* nothing */ } while (0)
+#define say2(a,b,c) do { /* nothing */ } while (0)
#endif
static const char en85[] = {
else if (get_sha1(patch->old_sha1_prefix, sha1))
/* git diff has no index line for mode/type changes */
if (!patch->lines_added && !patch->lines_deleted) {
- if (get_current_sha1(patch->new_name, sha1) ||
- get_current_sha1(patch->old_name, sha1))
+ if (get_current_sha1(patch->old_name, sha1))
die("mode change for %s, which is not "
"in current HEAD", name);
sha1_ptr = sha1;
*
* The remaining are:
*
- * (1) if dashdash_pos != 0, its either
+ * (1) if dashdash_pos != 0, it is either
* "blame [revisions] -- <path>" or
* "blame -- <path> <rev>"
*
- * (2) otherwise, its one of the two:
+ * (2) otherwise, it is one of the two:
* "blame [revisions] <path>"
* "blame <path> <rev>"
*
*dst = '\0';
}
+static int check_ref_format_branch(const char *arg)
+{
+ struct strbuf sb = STRBUF_INIT;
+ int nongit;
+
+ setup_git_directory_gently(&nongit);
+ if (strbuf_check_branch_ref(&sb, arg))
+ die("'%s' is not a valid branch name", arg);
+ printf("%s\n", sb.buf + 11);
+ return 0;
+}
+
+static int check_ref_format_print(const char *arg)
+{
+ char *refname = xmalloc(strlen(arg) + 1);
+
+ if (check_ref_format(arg))
+ return 1;
+ collapse_slashes(refname, arg);
+ printf("%s\n", refname);
+ return 0;
+}
+
int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
{
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(builtin_check_ref_format_usage);
- if (argc == 3 && !strcmp(argv[1], "--branch")) {
- struct strbuf sb = STRBUF_INIT;
-
- if (strbuf_check_branch_ref(&sb, argv[2]))
- die("'%s' is not a valid branch name", argv[2]);
- printf("%s\n", sb.buf + 11);
- exit(0);
- }
- if (argc == 3 && !strcmp(argv[1], "--print")) {
- char *refname = xmalloc(strlen(argv[2]) + 1);
-
- if (check_ref_format(argv[2]))
- exit(1);
- collapse_slashes(refname, argv[2]);
- printf("%s\n", refname);
- exit(0);
- }
+ if (argc == 3 && !strcmp(argv[1], "--branch"))
+ return check_ref_format_branch(argv[2]);
+ if (argc == 3 && !strcmp(argv[1], "--print"))
+ return check_ref_format_print(argv[2]);
if (argc != 2)
usage(builtin_check_ref_format_usage);
return !!check_ref_format(argv[1]);
struct rev_info rev;
/* I think we want full paths, even if we're in a subdirectory. */
init_revisions(&rev, NULL);
- rev.abbrev = 0;
rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS;
if (diff_setup_done(&rev.diffopt) < 0)
die("diff_setup_done failed");
"terminate entries with NUL"),
OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"),
- { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
+ { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
/* end commit contents options */
{ OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL,
init_revisions(&rev, prefix);
setup_revisions(0, NULL, &rev, NULL);
- rev.abbrev = 0;
rev.diff = 1;
rev.diffopt.output_format =
DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
int exit_code;
if (!remote)
- die("Where do you want to fetch from today?");
+ die("No remote repository specified. Please, specify either a URL or a\n"
+ "remote name from which new revisions should be fetched.");
transport = transport_get(remote, NULL);
transport_set_verbosity(transport, verbosity, progress);
v->s = s;
}
else if (!strcmp(name, "objectname:short")) {
- v->s = find_unique_abbrev(obj->sha1, DEFAULT_ABBREV);
+ v->s = xstrdup(find_unique_abbrev(obj->sha1,
+ DEFAULT_ABBREV));
}
}
}
if (!path)
path = "emacsclient";
strbuf_addf(&man_page, "(woman \"%s\")", page);
- execlp(path, "emacsclient", "-e", man_page.buf, NULL);
+ execlp(path, "emacsclient", "-e", man_page.buf, (char *)NULL);
warning("failed to exec '%s': %s", path, strerror(errno));
}
}
} else
path = "kfmclient";
strbuf_addf(&man_page, "man:%s(1)", page);
- execlp(path, filename, "newTab", man_page.buf, NULL);
+ execlp(path, filename, "newTab", man_page.buf, (char *)NULL);
warning("failed to exec '%s': %s", path, strerror(errno));
}
}
{
if (!path)
path = "man";
- execlp(path, "man", page, NULL);
+ execlp(path, "man", page, (char *)NULL);
warning("failed to exec '%s': %s", path, strerror(errno));
}
{
struct strbuf shell_cmd = STRBUF_INIT;
strbuf_addf(&shell_cmd, "%s %s", cmd, page);
- execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL);
+ execl("/bin/sh", "sh", "-c", shell_cmd.buf, (char *)NULL);
warning("failed to exec '%s': %s", cmd, strerror(errno));
}
{
const char *page = cmd_to_page(git_cmd);
setenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
- execlp("info", "info", "gitman", page, NULL);
+ execlp("info", "info", "gitman", page, (char *)NULL);
die("no info viewer handled the request");
}
#ifndef open_html
static void open_html(const char *path)
{
- execl_git_cmd("web--browse", "-c", "help.browser", path, NULL);
+ execl_git_cmd("web--browse", "-c", "help.browser", path, (char *)NULL);
}
#endif
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(index_pack_usage);
+ read_replace_refs = 0;
+
/*
* We wish to read the repository's config file if any, and
* for that it is necessary to call setup_git_directory_gently().
rev->show_decorations = 1;
load_ref_decorations(decoration_style);
}
+ setup_pager();
}
/*
rev.use_terminator = 1;
rev.always_show_header = 1;
- /*
- * We get called through "git reflog", so unlike the other log
- * routines, we need to set up our pager manually..
- */
- setup_pager();
-
return cmd_log_walk(&rev);
}
struct notes_tree *t;
int show_only = 0, verbose = 0;
struct option options[] = {
- OPT_BOOLEAN('n', NULL, &show_only, "do not remove, show only"),
- OPT_BOOLEAN('v', NULL, &verbose, "report pruned notes"),
+ OPT_BOOLEAN('n', "dry-run", &show_only,
+ "do not remove, show only"),
+ OPT_BOOLEAN('v', "verbose", &verbose, "report pruned notes"),
OPT_END()
};
{
struct rev_info revs;
const struct option options[] = {
- OPT_BOOLEAN('n', NULL, &show_only,
+ OPT_BOOLEAN('n', "dry-run", &show_only,
"do not remove, show only"),
- OPT_BOOLEAN('v', NULL, &verbose,
- "report pruned objects"),
+ OPT_BOOLEAN('v', "verbose", &verbose, "report pruned objects"),
OPT_DATE(0, "expire", &expire,
"expire objects older than <time>"),
OPT_END()
if (nonfastforward && advice_push_nonfastforward) {
fprintf(stderr, "To prevent you from losing history, non-fast-forward updates were rejected\n"
- "Merge the remote changes before pushing again. See the 'Note about\n"
- "fast-forwards' section of 'git push --help' for details.\n");
+ "Merge the remote changes (e.g. 'git pull') before pushing again. See the\n"
+ "'Note about fast-forwards' section of 'git push --help' for details.\n");
}
return 1;
mode = ce->ce_mode;
entlen = pathlen - baselen;
}
- if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1))
+ if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) {
+ strbuf_release(&buffer);
return error("invalid object %06o %s for '%.*s'",
mode, sha1_to_hex(sha1), entlen+baselen, path);
+ }
if (ce->ce_flags & CE_REMOVE)
continue; /* entry being removed */
alloc = alloc_nr(alloc); \
x = xrealloc((x), alloc * sizeof(*(x))); \
} \
- } while(0)
+ } while (0)
/* Initialize and use the cache information */
extern int read_index(struct index_state *);
}
/*
- * Determines the absolute path of cmd using the the split path in path.
+ * Determines the absolute path of cmd using the split path in path.
* If cmd contains a slash or backslash, no lookup is performed.
*/
static char *path_lookup(const char *cmd, char **path, int exe_only)
Each freshly allocated chunk must have both cinuse and pinuse set.
That is, each allocated chunk borders either a previously allocated
and still in-use chunk, or the base of its memory arena. This is
- ensured by making all allocations from the the `lowest' part of any
+ ensured by making all allocations from the `lowest' part of any
found chunk. Further, no free chunk physically borders another one,
so each free chunk is known to be preceded and followed by either
inuse chunks or the ends of memory.
/* re_match_2 matches the compiled pattern in BUFP against the
- the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
+ (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
and SIZE2, respectively). We start matching at POS, and stop
matching at STOP.
if test -z "$quiet"
then
commit=`git diff-tree --always --shortstat --pretty="format:%h: %s"\
- --summary --root HEAD --`
+ --abbrev --summary --root HEAD --`
echo "Created${initial_commit:+ initial} commit $commit"
fi
fi
# Generate header
cat <<-EOF
To: $recipients
- Subject: ${emailprefix}$projectdesc $refname_type, $short_refname, ${change_type}d. $describe
+ Subject: ${emailprefix}$projectdesc $refname_type $short_refname ${change_type}d. $describe
X-Git-Refname: $refname
X-Git-Reftype: $refname_type
X-Git-Oldrev: $oldrev
/*.xml
/*.1
/*.html
+/svn-fe
$(ALL_LDFLAGS) $(LIBS)
svn-fe.o: svn-fe.c ../../vcs-svn/svndump.h
- $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
+ $(QUIET_CC)$(CC) -I../../vcs-svn -o $*.o -c $(ALL_CFLAGS) $<
svn-fe.html: svn-fe.txt
$(QUIET_SUBDIR0)../../Documentation $(QUIET_SUBDIR1) \
*/
#include <stdlib.h>
-#include "vcs-svn/svndump.h"
+#include "svndump.h"
int main(int argc, char **argv)
{
die "destination directory '$new_workdir' already exists."
fi
-# make sure the the links use full paths
+# make sure the links use full paths
git_dir=$(cd "$git_dir"; pwd)
# create the workdir
mkdir -p "$new_workdir/.git" || die "unable to create \"$new_workdir\"!"
-# create the links to the original repo. explictly exclude index, HEAD and
+# create the links to the original repo. explicitly exclude index, HEAD and
# logs/HEAD from the list since they are purely related to the current working
# directory, and should not be shared.
for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache svn
static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
{
/* Strip the prefix but do not molest /dev/null and absolute paths */
- if (*namep && **namep != '/')
+ if (*namep && **namep != '/') {
*namep += prefix_length;
- if (*otherp && **otherp != '/')
+ if (**namep == '/')
+ ++*namep;
+ }
+ if (*otherp && **otherp != '/') {
*otherp += prefix_length;
+ if (**otherp == '/')
+ ++*otherp;
+ }
}
static void run_diff(struct diff_filepair *p, struct diff_options *o)
void diff_setup(struct diff_options *options)
{
memset(options, 0, sizeof(*options));
- memset(&diff_queued_diff, 0, sizeof(diff_queued_diff));
options->file = stdout;
void diffcore_std(struct diff_options *options)
{
- /* We never run this function more than one time, because the
- * rename/copy detection logic can only run once.
- */
- if (diff_queued_diff.run)
- return;
-
if (options->skip_stat_unmatch)
diffcore_skip_stat_unmatch(options);
- if (options->break_opt != -1)
- diffcore_break(options->break_opt);
- if (options->detect_rename)
- diffcore_rename(options);
- if (options->break_opt != -1)
- diffcore_merge_broken();
+ if (!options->found_follow) {
+ /* See try_to_follow_renames() in tree-diff.c */
+ if (options->break_opt != -1)
+ diffcore_break(options->break_opt);
+ if (options->detect_rename)
+ diffcore_rename(options);
+ if (options->break_opt != -1)
+ diffcore_merge_broken();
+ }
if (options->pickaxe)
diffcore_pickaxe(options->pickaxe, options->pickaxe_opts);
if (options->orderfile)
diffcore_order(options->orderfile);
- diff_resolve_rename_copy();
+ if (!options->found_follow)
+ /* See try_to_follow_renames() in tree-diff.c */
+ diff_resolve_rename_copy();
diffcore_apply_filter(options->filter);
if (diff_queued_diff.nr && !DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
else
DIFF_OPT_CLR(options, HAS_CHANGES);
- diff_queued_diff.run = 1;
+ options->found_follow = 0;
}
int diff_result_code(struct diff_options *opt, int status)
/* this is set by diffcore for DIFF_FORMAT_PATCH */
int found_changes;
+ /* to support internal diff recursion by --follow hack*/
+ int found_follow;
+
FILE *file;
int close_file;
#define MAX_SCORE 60000.0
#define DEFAULT_RENAME_SCORE 30000 /* rename/copy similarity minimum (50%) */
#define DEFAULT_BREAK_SCORE 30000 /* minimum for break to happen (50%) */
-#define DEFAULT_MERGE_SCORE 36000 /* maximum for break-merge to happen 60%) */
+#define DEFAULT_MERGE_SCORE 36000 /* maximum for break-merge to happen (60%) */
#define MINIMUM_BREAK_SIZE 400 /* do not break a file smaller than this */
struct diff_filepair **queue;
int alloc;
int nr;
- int run;
};
#define DIFF_QUEUE_CLEAR(q) \
do { \
(q)->queue = NULL; \
(q)->nr = (q)->alloc = 0; \
- (q)->run = 0; \
- } while(0);
+ } while (0)
extern struct diff_queue_struct diff_queued_diff;
extern struct diff_filepair *diff_queue(struct diff_queue_struct *,
void diff_debug_filepair(const struct diff_filepair *, int);
void diff_debug_queue(const char *, struct diff_queue_struct *);
#else
-#define diff_debug_filespec(a,b,c) do {} while(0)
-#define diff_debug_filepair(a,b) do {} while(0)
-#define diff_debug_queue(a,b) do {} while(0)
+#define diff_debug_filespec(a,b,c) do { /* nothing */ } while (0)
+#define diff_debug_filepair(a,b) do { /* nothing */ } while (0)
+#define diff_debug_queue(a,b) do { /* nothing */ } while (0)
#endif
extern int diffcore_count_changes(struct diff_filespec *src,
if (m->shift) {
for (k = 0; k < 1024; k++) {
if (m->data.sets[k])
- dump_marks_helper(f, (base + k) << m->shift,
+ dump_marks_helper(f, base + (k << m->shift),
m->data.sets[k]);
}
} else {
static inline size_t xsize_t(off_t len)
{
+ if (len > (size_t) len)
+ die("Cannot handle files this big");
return (size_t)len;
}
tk_messageBox \
-icon error \
-type ok \
- -title [mc "git-gui: fatal error"] \
+ -title "git-gui: fatal error" \
-message $err
exit 1
}
}
}
+proc is_config_false {name} {
+ global repo_config
+ if {[catch {set v $repo_config($name)}]} {
+ return 0
+ } elseif {$v eq {false} || $v eq {0} || $v eq {no}} {
+ return 1
+ } else {
+ return 0
+ }
+}
+
proc get_config {name} {
global repo_config
if {[catch {set v $repo_config($name)}]} {
puts stderr $d
}
+#'" fix poor old emacs font-lock mode
+
proc _git_cmd {name} {
global _git_cmd_path
if {![info exists _nice]} {
set _nice [_which nice]
+ if {[catch {exec $_nice git version}]} {
+ set _nice {}
+ }
}
if {$_nice ne {}} {
lappend cmd $_nice
return $text
}
+wm withdraw .
set root_exists 0
bind . <Visibility> {
bind . <Visibility> {}
set default_config(gui.encoding) [encoding system]
set default_config(gui.matchtrackingbranch) false
+set default_config(gui.textconv) true
set default_config(gui.pruneduringfetch) false
set default_config(gui.trustmtime) false
set default_config(gui.fastcopyblame) false
# try to set work tree from environment, falling back to core.worktree
if {[catch { set _gitworktree $env(GIT_WORK_TREE) }]} {
set _gitworktree [get_config core.worktree]
+ if {$_gitworktree eq ""} {
+ set _gitworktree [file dirname [file normalize $_gitdir]]
+ }
}
if {$_prefix ne {}} {
if {$_gitworktree eq {}} {
# freedesktop.org-conforming system is our best shot
set explorer "xdg-open"
}
- eval exec $explorer $_gitworktree &
+ eval exec $explorer [list [file nativename $_gitworktree]] &
}
set is_quitting 0
set current_branch $head
}
+ wm deiconify .
switch -- $subcommand {
browser {
if {$jump_spec ne {}} usage
$ctxmsm add separator
create_common_diff_popup $ctxmsm
+proc has_textconv {path} {
+ if {[is_config_false gui.textconv]} {
+ return 0
+ }
+ set filter [gitattr $path diff set]
+ set textconv [get_config [join [list diff $filter textconv] .]]
+ if {$filter ne {set} && $textconv ne {}} {
+ return 1
+ } else {
+ return 0
+ }
+}
+
proc popup_diff_menu {ctxm ctxmmg ctxmsm x y X Y} {
global current_diff_path file_states
set ::cursorX $x
|| {__} eq $state
|| {_O} eq $state
|| {_T} eq $state
- || {T_} eq $state} {
+ || {T_} eq $state
+ || [has_textconv $current_diff_path]} {
set s disabled
} else {
set s normal
# -- Load geometry
#
-catch {
-set gm $repo_config(gui.geometry)
-wm geometry . [lindex $gm 0]
-if {$use_ttk} {
- .vpane sashpos 0 [lindex $gm 1]
- .vpane.files sashpos 0 [lindex $gm 2]
-} else {
- .vpane sash place 0 \
- [lindex $gm 1] \
- [lindex [.vpane sash coord 0] 1]
- .vpane.files sash place 0 \
- [lindex [.vpane.files sash coord 0] 0] \
- [lindex $gm 2]
+proc on_ttk_pane_mapped {w pane pos} {
+ bind $w <Map> {}
+ after 0 [list after idle [list $w sashpos $pane $pos]]
+}
+proc on_tk_pane_mapped {w pane x y} {
+ bind $w <Map> {}
+ after 0 [list after idle [list $w sash place $pane $x $y]]
+}
+proc on_application_mapped {} {
+ global repo_config use_ttk
+ bind . <Map> {}
+ set gm $repo_config(gui.geometry)
+ if {$use_ttk} {
+ bind .vpane <Map> \
+ [list on_ttk_pane_mapped %W 0 [lindex $gm 1]]
+ bind .vpane.files <Map> \
+ [list on_ttk_pane_mapped %W 0 [lindex $gm 2]]
+ } else {
+ bind .vpane <Map> \
+ [list on_tk_pane_mapped %W 0 \
+ [lindex $gm 1] \
+ [lindex [.vpane sash coord 0] 1]]
+ bind .vpane.files <Map> \
+ [list on_tk_pane_mapped %W 0 \
+ [lindex [.vpane.files sash coord 0] 0] \
+ [lindex $gm 2]]
+ }
+ wm geometry . [lindex $gm 0]
}
-unset gm
+if {[info exists repo_config(gui.geometry)]} {
+ bind . <Map> [list on_application_mapped]
+ wm geometry . [lindex $repo_config(gui.geometry) 0]
}
# -- Load window state
#
-catch {
-set gws $repo_config(gui.wmstate)
-wm state . $gws
-unset gws
+if {[info exists repo_config(gui.wmstate)]} {
+ catch {wm state . $repo_config(gui.wmstate)}
}
# -- Key Bindings
$status show [mc "Reading %s..." "$commit:[escape_path $path]"]
$w_path conf -text [escape_path $path]
+
+ set do_textconv 0
+ if {![is_config_false gui.textconv] && [git-version >= 1.7.2]} {
+ set filter [gitattr $path diff set]
+ set textconv [get_config [join [list diff $filter textconv] .]]
+ if {$filter ne {set} && $textconv ne {}} {
+ set do_textconv 1
+ }
+ }
if {$commit eq {}} {
- set fd [open $path r]
+ if {$do_textconv ne 0} {
+ set fd [open |[list $textconv $path] r]
+ } else {
+ set fd [open $path r]
+ }
fconfigure $fd -eofchar {}
} else {
- set fd [git_read cat-file blob "$commit:$path"]
+ if {$do_textconv ne 0} {
+ set fd [git_read cat-file --textconv "$commit:$path"]
+ } else {
+ set fd [git_read cat-file blob "$commit:$path"]
+ }
}
fconfigure $fd \
-blocking 0 \
$opts insert end [mc "Clone Existing Repository"] link_clone
$opts insert end "\n"
if {$m_repo ne {}} {
+ if {[tk windowingsystem] eq "win32"} {
+ set key L
+ } else {
+ set key C
+ }
$m_repo add command \
-command [cb _next clone] \
- -accelerator $M1T-C \
+ -accelerator $M1T-$key \
-label [mc "Clone..."]
- bind $top <$M1B-c> [cb _next clone]
- bind $top <$M1B-C> [cb _next clone]
+ bind $top <$M1B-[string tolower $key]> [cb _next clone]
+ bind $top <$M1B-[string toupper $key]> [cb _next clone]
}
$opts tag conf link_open -foreground blue -underline 1
set path $current_diff_path
set s $file_states($path)
- if {[lindex $s 0] ne {_M}} return
+ if {[lindex $s 0] ne {_M} || [has_textconv $path]} return
# Prevent infinite rescan loops
incr diff_empty_count
lappend cmd diff-files
}
}
+ if {![is_config_false gui.textconv] && [git-version >= 1.6.1]} {
+ lappend cmd --textconv
+ }
if {[string match {160000 *} [lindex $s 2]]
|| [string match {160000 *} [lindex $s 3]]} {
{b gui.trustmtime {mc "Trust File Modification Timestamps"}}
{b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}}
{b gui.matchtrackingbranch {mc "Match Tracking Branches"}}
+ {b gui.textconv {mc "Use Textconv For Diffs and Blames"}}
{b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}}
{i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}}
{i-0..300 gui.blamehistoryctx {mc "Blame History Context Radius (days)"}}
[info nameofexecutable] \
[file normalize $::argv0] \
] \
- [file normalize [$_gitworktree]]
+ [file normalize $_gitworktree]
} err]} {
error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]
}
$sh -c \
"CHERE_INVOKING=1 source /etc/profile;[sq $me] &" \
] \
- [file normalize [$_gitworktree]]
+ [file normalize $_gitworktree]
} err]} {
error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]
}
}
constructor two_line {path} {
+ global NS
set w $path
set w_l $w.l
set w_c $w.c
eval [list exec wscript.exe \
/E:jscript \
/nologo \
- [file join $oguilib win32_shortcut.js] \
+ [file nativename [file join $oguilib win32_shortcut.js]] \
$lnk_path \
- [file join $oguilib git-gui.ico] \
+ [file nativename [file join $oguilib git-gui.ico]] \
$lnk_dir \
$lnk_exec] $lnk_args
}
incr argc -2
}
-set bindir [file dirname \
+set basedir [file dirname \
[file dirname \
[file dirname [info script]]]]
-set bindir [file join $bindir bin]
+set bindir [file join $basedir bin]
+set bindir "$bindir;[file join $basedir mingw bin]"
regsub -all ";" $bindir "\\;" bindir
set env(PATH) "$bindir;$env(PATH)"
unset bindir
resolve_full_httpd () {
case "$httpd" in
- *apache2*|*lighttpd*)
+ *apache2*|*lighttpd*|*httpd*)
+ # yes, *httpd* covers *lighttpd* above, but it is there for clarity
# ensure that the apache2/lighttpd command ends with "-f"
if ! echo "$httpd" | sane_grep -- '-f *$' >/dev/null 2>&1
then
}
apache2_conf () {
- test -z "$module_path" && module_path=/usr/lib/apache2/modules
+ if test -z "$module_path"
+ then
+ test -d "/usr/lib/httpd/modules" &&
+ module_path="/usr/lib/httpd/modules"
+ test -d "/usr/lib/apache2/modules" &&
+ module_path="/usr/lib/apache2/modules"
+ fi
bind=
test x"$local" = xtrue && bind='127.0.0.1:'
echo 'text/css css' > "$fqgitdir/mime.types"
Listen $bind$port
EOF
- for mod in mime dir; do
- if test -e $module_path/mod_${mod}.so; then
+ for mod in mime dir env log_config
+ do
+ if test -e $module_path/mod_${mod}.so
+ then
echo "LoadModule ${mod}_module " \
"$module_path/mod_${mod}.so" >> "$conf"
fi
cat >> "$conf" <<EOF
LoadModule perl_module $module_path/mod_perl.so
PerlPassEnv GIT_DIR
-PerlPassEnv GIT_EXEC_DIR
+PerlPassEnv GIT_EXEC_PATH
PerlPassEnv GITWEB_CONFIG
<Location /gitweb.cgi>
SetHandler perl-script
echo "ScriptSock logs/gitweb.sock" >> "$conf"
fi
cat >> "$conf" <<EOF
+PassEnv GIT_DIR
+PassEnv GIT_EXEC_PATH
+PassEnv GITWEB_CONFIG
AddHandler cgi-script .cgi
<Location /gitweb.cgi>
Options +ExecCGI
*lighttpd*)
lighttpd_conf
;;
-*apache2*)
+*apache2*|*httpd*)
apache2_conf
;;
webrick)
exit
fi
+if test true = "$rebase"
+then
+ o=$(git show-branch --merge-base $curr_branch $merge_head $oldremoteref)
+ if test "$oldremoteref" = "$o"
+ then
+ unset oldremoteref
+ fi
+fi
+
merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
case "$rebase" in
true)
export GIT_CHERRY_PICK_HELP
warn () {
- echo "$*" >&2
+ printf '%s\n' "$*" >&2
}
output () {
fd=1
;;
esac
- echo "$command${sha1:+ }$sha1${rest:+ }$rest" >&$fd
+ printf '%s\n' "$command${sha1:+ }$sha1${rest:+ }$rest" >&$fd
done <"$TODO" >"$TODO.new" 3>>"$DONE" &&
mv -f "$TODO".new "$TODO" &&
case "$(peek_next_command)" in
case " $used" in
*" $sha1 "*) continue ;;
esac
- echo "$pick $sha1 $message"
+ printf '%s\n' "$pick $sha1 $message"
while read -r squash action msg
do
case "$message" in
"$msg"*)
- echo "$action $squash $action! $msg"
+ printf '%s\n' "$action $squash $action! $msg"
used="$used$squash "
;;
esac
do
if test t != "$PRESERVE_MERGES"
then
- echo "pick $shortsha1 $rest" >> "$TODO"
+ printf '%s\n' "pick $shortsha1 $rest" >> "$TODO"
else
sha1=$(git rev-parse $shortsha1)
if test -z "$REBASE_ROOT"
if test f = "$preserve"
then
touch "$REWRITTEN"/$sha1
- echo "pick $shortsha1 $rest" >> "$TODO"
+ printf '%s\n' "pick $shortsha1 $rest" >> "$TODO"
fi
fi
done
test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
die "No rebase in progress?"
+ git update-index --ignore-submodules --refresh &&
git diff-files --quiet --ignore-submodules || {
echo "You must edit all merge conflicts and then"
echo "mark them as resolved using git add"
--root)
rebase_root=t
;;
- -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase|--no-ff)
+ -f|--f|--fo|--for|--forc|--force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase|--no-ff)
force_rebase=t
;;
--rerere-autoupdate|--no-rerere-autoupdate)
if test -z "$do_merge"
then
git format-patch -k --stdout --full-index --ignore-if-in-upstream \
- $root_flag "$revisions" |
+ --no-renames $root_flag "$revisions" |
git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
move_to_original_branch
ret=$?
valid_tool() {
case "$1" in
- firefox | iceweasel | chrome | chromium | konqueror | w3m | links | lynx | dillo | open | start)
+ firefox | iceweasel | chrome | google-chrome | chromium | konqueror | w3m | links | lynx | dillo | open | start)
;; # happy
*)
valid_custom_tool "$1" || return 1
if test -z "$browser" ; then
if test -n "$DISPLAY"; then
- browser_candidates="firefox iceweasel chrome chromium konqueror w3m links lynx dillo"
+ browser_candidates="firefox iceweasel google-chrome chrome chromium konqueror w3m links lynx dillo"
if test "$KDE_FULL_SESSION" = "true"; then
browser_candidates="konqueror $browser_candidates"
fi
test "$vers" -lt 2 && NEWTAB=''
"$browser_path" $NEWTAB "$@" &
;;
- chrome|chromium)
+ google-chrome|chrome|chromium)
# Actual command for chromium is chromium-browser.
# No need to specify newTab. It's default in chromium
eval "$browser_path" "$@" &
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
" [-p|--paginate|--no-pager] [--no-replace-objects]\n"
" [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n"
- " [-c name=value\n"
- " [--help] COMMAND [ARGS]";
+ " [-c name=value] [--help]\n"
+ " COMMAND [ARGS]";
const char git_more_info_string[] =
"See 'git help COMMAND' for more information on a specific command.";
{ "index-pack", cmd_index_pack },
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
- { "log", cmd_log, RUN_SETUP | USE_PAGER },
+ { "log", cmd_log, RUN_SETUP },
{ "ls-files", cmd_ls_files, RUN_SETUP },
{ "ls-tree", cmd_ls_tree, RUN_SETUP },
{ "ls-remote", cmd_ls_remote },
{ "send-pack", cmd_send_pack, RUN_SETUP },
{ "shortlog", cmd_shortlog, USE_PAGER },
{ "show-branch", cmd_show_branch, RUN_SETUP },
- { "show", cmd_show, RUN_SETUP | USE_PAGER },
+ { "show", cmd_show, RUN_SETUP },
{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
{ "stripspace", cmd_stripspace },
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
{ "var", cmd_var },
{ "verify-tag", cmd_verify_tag, RUN_SETUP },
{ "version", cmd_version },
- { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },
+ { "whatchanged", cmd_whatchanged, RUN_SETUP },
{ "write-tree", cmd_write_tree, RUN_SETUP },
{ "verify-pack", cmd_verify_pack },
{ "show-ref", cmd_show_ref, RUN_SETUP },
in the browser's URL bar and next to site name in bookmarks). Relative
to base URI of gitweb. [Default: static/git-favicon.png]
* GITWEB_JS
- Points to the localtion where you put gitweb.js on your web server
+ Points to the location where you put gitweb.js on your web server
(or to be more generic URI of JavaScript code used by gitweb).
Relative to base URI of gitweb. [Default: static/gitweb.js (or
static/gitweb.min.js if JSMIN build variable is defined / JavaScript
is false.
* $maxload
Used to set the maximum load that we will still respond to gitweb queries.
- If server load exceed this value then return "503 Service Unavaliable" error.
+ If server load exceed this value then return "503 Service Unavailable" error.
Server load is taken to be 0 if gitweb cannot determine its value. Set it to
undefined value to turn it off. The default is 300.
# return value of feature-sub indicates if to enable specified feature
#
# if there is no 'sub' key (no feature-sub), then feature cannot be
- # overriden
+ # overridden
#
# use gitweb_get_feature(<feature>) to retrieve the <feature> value
# (an array) or gitweb_check_feature(<feature>) to check if <feature>
return $str;
}
-# quote unsafe chars in whole URL, so some charactrs cannot be quoted
+# quote unsafe chars in whole URL, so some characters cannot be quoted
sub esc_url {
my $str = shift;
return undef unless defined $str;
}
# Outputs table rows containing the full author or committer information,
-# in the format expected for 'commit' view (& similia).
+# in the format expected for 'commit' view (& similar).
# Parameters are a commit hash reference, followed by the list of people
-# to output information for. If the list is empty it defalts to both
+# to output information for. If the list is empty it defaults to both
# author and committer.
sub git_print_authorship_rows {
my $co = shift;
print "</div>\n"; # class="patch"
}
- # for compact combined (--cc) format, with chunk and patch simpliciaction
- # patchset might be empty, but there might be unprocessed raw lines
+ # for compact combined (--cc) format, with chunk and patch simplification
+ # the patchset might be empty, but there might be unprocessed raw lines
for (++$patch_idx if $patch_number > 0;
$patch_idx < @$difftree;
++$patch_idx) {
$paging_nav .= " ⋅ next";
}
- if ($#commitlist >= 100) {
- }
-
git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav);
git_print_header_div('commit', esc_html($co{'title'}), $hash);
- git_search_grep_body(\@commitlist, 0, 99, $next_link);
+ if ($page == 0 && !@commitlist) {
+ print "<p>No match.</p>\n";
+ } else {
+ git_search_grep_body(\@commitlist, 0, 99, $next_link);
+ }
}
if ($searchtype eq 'pickaxe') {
max_cols++;
/*
- * We added a column for the the current commit as part of
+ * We added a column for the current commit as part of
* graph->num_parents. If the current commit was already in
* graph->columns, then we have double counted it.
*/
#endif
#if LIBCURL_VERSION_NUM < 0x070704
-#define curl_global_cleanup() do { /* nothing */ } while(0)
+#define curl_global_cleanup() do { /* nothing */ } while (0)
#endif
#if LIBCURL_VERSION_NUM < 0x070800
-#define curl_global_init(a) do { /* nothing */ } while(0)
+#define curl_global_init(a) do { /* nothing */ } while (0)
#endif
#if (LIBCURL_VERSION_NUM < 0x070c04) || (LIBCURL_VERSION_NUM == 0x071000)
while (imap->literal_pending)
get_cmd_result(ctx, NULL);
- bufl = nfsnprintf(buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ?
- "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
- cmd->tag, cmd->cmd, cmd->cb.dlen);
+ if (!cmd->cb.data)
+ bufl = nfsnprintf(buf, sizeof(buf), "%d %s\r\n", cmd->tag, cmd->cmd);
+ else
+ bufl = nfsnprintf(buf, sizeof(buf), "%d %s{%d%s}\r\n",
+ cmd->tag, cmd->cmd, cmd->cb.dlen,
+ CAP(LITERALPLUS) ? "+" : "");
+
if (Verbose) {
if (imap->num_in_progress)
printf("(%d in progress) ", imap->num_in_progress);
int gai;
char portstr[6];
- snprintf(portstr, sizeof(portstr), "%hu", srvc->port);
+ snprintf(portstr, sizeof(portstr), "%d", srvc->port);
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
err = error("%s SHA1 checksum mismatch",
p->pack_name);
if (hashcmp(index_base + index_size - 40, pack_sig))
- err = error("%s SHA1 does not match its inddex",
+ err = error("%s SHA1 does not match its index",
p->pack_name);
unuse_pack(w_curs);
* `flags`::
* mask of parse_opt_option_flags.
* PARSE_OPT_OPTARG: says that the argument is optional (not for BOOLEANs)
- * PARSE_OPT_NOARG: says that this option takes no argument
+ * PARSE_OPT_NOARG: says that this option does not take an argument
* PARSE_OPT_NONEG: says that this option cannot be negated
* PARSE_OPT_HIDDEN: this option is skipped in the default usage, and
* shown only in the full usage.
size_t username_len = first_slash - username;
if (username_len == 0) {
const char *home = getenv("HOME");
+ if (!home)
+ goto return_null;
strbuf_add(&user_path, home, strlen(home));
} else {
struct passwd *pw = getpw_str(username, username_len);
int size = ondisk_ce_size(ce);
struct ondisk_cache_entry *ondisk = xcalloc(1, size);
char *name;
+ int result;
ondisk->ctime.sec = htonl(ce->ce_ctime.sec);
ondisk->mtime.sec = htonl(ce->ce_mtime.sec);
name = ondisk->name;
memcpy(name, ce->name, ce_namelen(ce));
- return ce_write(c, fd, ondisk, size);
+ result = ce_write(c, fd, ondisk, size);
+ free(ondisk);
+ return result;
}
int write_index(struct index_state *istate, int newfd)
rpc->len = n;
err |= post_rpc(rpc);
}
- strbuf_read(&rpc->result, client.out, 0);
close(client.in);
- close(client.out);
client.in = -1;
+ strbuf_read(&rpc->result, client.out, 0);
+
+ close(client.out);
client.out = -1;
err |= finish_command(&client);
return get_short_sha1(name, len, sha1, 0);
}
+/*
+ * This interprets names like ':/Initial revision of "git"' by searching
+ * through history and returning the first commit whose message starts
+ * the given regular expression.
+ *
+ * For future extension, ':/!' is reserved. If you want to match a message
+ * beginning with a '!', you have to repeat the exclamation mark.
+ */
+#define ONELINE_SEEN (1u<<20)
+
static int handle_one_ref(const char *path,
const unsigned char *sha1, int flag, void *cb_data)
{
if (object->type != OBJ_COMMIT)
return 0;
insert_by_date((struct commit *)object, list);
+ object->flags |= ONELINE_SEEN;
return 0;
}
-/*
- * This interprets names like ':/Initial revision of "git"' by searching
- * through history and returning the first commit whose message matches
- * the given regular expression.
- *
- * For future extension, ':/!' is reserved. If you want to match a message
- * beginning with a '!', you have to repeat the exclamation mark.
- */
-
-#define ONELINE_SEEN (1u<<20)
static int get_sha1_oneline(const char *prefix, unsigned char *sha1)
{
struct commit_list *list = NULL, *backup = NULL, *l;
GIT_DIR=$PWD/.git
GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn
SVN_TREE=$GIT_SVN_DIR/svn-tree
-PERL=${PERL:-perl}
svn >/dev/null 2>&1
if test $? -ne 1
svnconf=$PWD/svnconf
export svnconf
-$PERL -w -e "
+"$PERL_PATH" -w -e "
use SVN::Core;
use SVN::Repos;
\$SVN::Core::VERSION gt '1.1.0' or exit(42);
}
convert_to_rev_db () {
- $PERL -w -- - "$@" <<\EOF
+ "$PERL_PATH" -w -- - "$@" <<\EOF
use strict;
@ARGV == 2 or die "Usage: convert_to_rev_db <input> <output>";
open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]";
attr_check a/b/g a/b/g &&
attr_check b/g unspecified &&
attr_check a/b/h a/b/h &&
- attr_check a/b/d/g "a/b/d/*"
- attr_check onoff unset
- attr_check offon set
- attr_check no unspecified
- attr_check a/b/d/no "a/b/d/*"
+ attr_check a/b/d/g "a/b/d/*" &&
+ attr_check onoff unset &&
+ attr_check offon set &&
+ attr_check no unspecified &&
+ attr_check a/b/d/no "a/b/d/*" &&
attr_check a/b/d/yes unspecified
'
git config --path path.trailingtilde "foo~" &&
test_cmp expect .git/config'
+if test "${HOME+set}"
+then
+ test_set_prereq HOMEVAR
+fi
+
cat >expect <<EOF
$HOME/
/dev/null
foo~
EOF
-test_expect_success 'get --path' '
+test_expect_success HOMEVAR 'get --path' '
git config --get --path path.home > result &&
git config --get --path path.normal >> result &&
git config --get --path path.trailingtilde >> result &&
test_cmp expect result
'
+cat >expect <<\EOF
+/dev/null
+foo~
+EOF
+
+test_expect_success 'get --path copes with unset $HOME' '
+ (
+ unset HOME;
+ test_must_fail git config --get --path path.home \
+ >result 2>msg &&
+ git config --get --path path.normal >>result &&
+ git config --get --path path.trailingtilde >>result
+ ) &&
+ grep "[Ff]ailed to expand.*~/" msg &&
+ test_cmp expect result
+'
+
rm .git/config
git config quote.leading " test"
refname2=$(git check-ref-format --branch @{-2}) &&
test "$refname2" = master'
+test_expect_success 'check-ref-format --branch from subdir' '
+ mkdir subdir &&
+
+ T=$(git write-tree) &&
+ sha1=$(echo A | git commit-tree $T) &&
+ git update-ref refs/heads/master $sha1 &&
+ git update-ref refs/remotes/origin/master $sha1
+ git checkout master &&
+ git checkout origin/master &&
+ git checkout master &&
+ refname=$(
+ cd subdir &&
+ git check-ref-format --branch @{-1}
+ ) &&
+ test "$refname" = "$sha1"
+'
+
valid_ref_normalized() {
test_expect_success "ref name '$1' simplifies to '$2'" "
refname=\$(git check-ref-format --print '$1') &&
for mode in no-notes notes
do
echo $mode
- /usr/bin/time sh ../time_notes $mode $1
+ /usr/bin/time "$SHELL_PATH" ../time_notes $mode $1
done
}
GIT_AUTHOR_EMAIL=bogus@email@address
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
-test_expect_success \
- 'prepare repository with topic branches' \
- 'git config core.logAllRefUpdates true &&
- echo First > A &&
- git update-index --add A &&
- git commit -m "Add A." &&
- git checkout -b my-topic-branch &&
- echo Second > B &&
- git update-index --add B &&
- git commit -m "Add B." &&
- git checkout -f master &&
- echo Third >> A &&
- git update-index A &&
- git commit -m "Modify A." &&
- git checkout -b side my-topic-branch &&
- echo Side >> C &&
- git add C &&
- git commit -m "Add C" &&
- git checkout -b nonlinear my-topic-branch &&
- echo Edit >> B &&
- git add B &&
- git commit -m "Modify B" &&
- git merge side &&
- git checkout -b upstream-merged-nonlinear &&
- git merge master &&
- git checkout -f my-topic-branch &&
- git tag topic
+test_expect_success 'prepare repository with topic branches' '
+ git config core.logAllRefUpdates true &&
+ echo First >A &&
+ git update-index --add A &&
+ git commit -m "Add A." &&
+ git checkout -b force-3way &&
+ echo Dummy >Y &&
+ git update-index --add Y &&
+ git commit -m "Add Y." &&
+ git checkout -b filemove &&
+ git reset --soft master &&
+ mkdir D &&
+ git mv A D/A &&
+ git commit -m "Move A." &&
+ git checkout -b my-topic-branch master &&
+ echo Second >B &&
+ git update-index --add B &&
+ git commit -m "Add B." &&
+ git checkout -f master &&
+ echo Third >>A &&
+ git update-index A &&
+ git commit -m "Modify A." &&
+ git checkout -b side my-topic-branch &&
+ echo Side >>C &&
+ git add C &&
+ git commit -m "Add C" &&
+ git checkout -b nonlinear my-topic-branch &&
+ echo Edit >>B &&
+ git add B &&
+ git commit -m "Modify B" &&
+ git merge side &&
+ git checkout -b upstream-merged-nonlinear &&
+ git merge master &&
+ git checkout -f my-topic-branch &&
+ git tag topic
'
test_expect_success 'rebase on dirty worktree' '
- echo dirty >> A &&
- test_must_fail git rebase master'
+ echo dirty >>A &&
+ test_must_fail git rebase master
+'
test_expect_success 'rebase on dirty cache' '
- git add A &&
- test_must_fail git rebase master'
+ git add A &&
+ test_must_fail git rebase master
+'
test_expect_success 'rebase against master' '
- git reset --hard HEAD &&
- git rebase master'
+ git reset --hard HEAD &&
+ git rebase master
+'
test_expect_success 'rebase against master twice' '
- git rebase master >out &&
- grep "Current branch my-topic-branch is up to date" out
+ git rebase master >out &&
+ grep "Current branch my-topic-branch is up to date" out
'
test_expect_success 'rebase against master twice with --force' '
- git rebase --force-rebase master >out &&
- grep "Current branch my-topic-branch is up to date, rebase forced" out
+ git rebase --force-rebase master >out &&
+ grep "Current branch my-topic-branch is up to date, rebase forced" out
'
test_expect_success 'rebase against master twice from another branch' '
- git checkout my-topic-branch^ &&
- git rebase master my-topic-branch >out &&
- grep "Current branch my-topic-branch is up to date" out
+ git checkout my-topic-branch^ &&
+ git rebase master my-topic-branch >out &&
+ grep "Current branch my-topic-branch is up to date" out
'
test_expect_success 'rebase fast-forward to master' '
- git checkout my-topic-branch^ &&
- git rebase my-topic-branch >out &&
- grep "Fast-forwarded HEAD to my-topic-branch" out
+ git checkout my-topic-branch^ &&
+ git rebase my-topic-branch >out &&
+ grep "Fast-forwarded HEAD to my-topic-branch" out
'
-test_expect_success \
- 'the rebase operation should not have destroyed author information' \
- '! (git log | grep "Author:" | grep "<>")'
+test_expect_success 'the rebase operation should not have destroyed author information' '
+ ! (git log | grep "Author:" | grep "<>")
+'
-test_expect_success \
- 'the rebase operation should not have destroyed author information (2)' \
- "git log -1 | grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>'"
+test_expect_success 'the rebase operation should not have destroyed author information (2)' "
+ git log -1 |
+ grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>'
+"
test_expect_success 'HEAD was detached during rebase' '
- test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1})
+ test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1})
'
test_expect_success 'rebase after merge master' '
- git reset --hard topic &&
- git merge master &&
- git rebase master &&
- ! (git show | grep "^Merge:")
+ git reset --hard topic &&
+ git merge master &&
+ git rebase master &&
+ ! (git show | grep "^Merge:")
'
test_expect_success 'rebase of history with merges is linearized' '
- git checkout nonlinear &&
- test 4 = $(git rev-list master.. | wc -l) &&
- git rebase master &&
- test 3 = $(git rev-list master.. | wc -l)
+ git checkout nonlinear &&
+ test 4 = $(git rev-list master.. | wc -l) &&
+ git rebase master &&
+ test 3 = $(git rev-list master.. | wc -l)
'
-test_expect_success \
- 'rebase of history with merges after upstream merge is linearized' '
- git checkout upstream-merged-nonlinear &&
- test 5 = $(git rev-list master.. | wc -l) &&
- git rebase master &&
- test 3 = $(git rev-list master.. | wc -l)
+test_expect_success 'rebase of history with merges after upstream merge is linearized' '
+ git checkout upstream-merged-nonlinear &&
+ test 5 = $(git rev-list master.. | wc -l) &&
+ git rebase master &&
+ test 3 = $(git rev-list master.. | wc -l)
'
test_expect_success 'rebase a single mode change' '
- git checkout master &&
- echo 1 > X &&
- git add X &&
- test_tick &&
- git commit -m prepare &&
- git checkout -b modechange HEAD^ &&
- echo 1 > X &&
- git add X &&
- test_chmod +x A &&
- test_tick &&
- git commit -m modechange &&
- GIT_TRACE=1 git rebase master
+ git checkout master &&
+ echo 1 >X &&
+ git add X &&
+ test_tick &&
+ git commit -m prepare &&
+ git checkout -b modechange HEAD^ &&
+ echo 1 >X &&
+ git add X &&
+ test_chmod +x A &&
+ test_tick &&
+ git commit -m modechange &&
+ GIT_TRACE=1 git rebase master
+'
+
+test_expect_success 'rebase is not broken by diff.renames' '
+ git config diff.renames copies &&
+ test_when_finished "git config --unset diff.renames" &&
+ git checkout filemove &&
+ GIT_TRACE=1 git rebase force-3way
+'
+
+test_expect_success 'setup: recover' '
+ test_might_fail git rebase --abort &&
+ git reset --hard &&
+ git checkout modechange
'
test_expect_success 'Show verbose error when HEAD could not be detached' '
- : > B &&
- test_must_fail git rebase topic 2> output.err > output.out &&
- grep "Untracked working tree file .B. would be overwritten" output.err
+ >B &&
+ test_must_fail git rebase topic 2>output.err >output.out &&
+ grep "Untracked working tree file .B. would be overwritten" output.err
'
rm -f B
test_expect_success 'dump usage when upstream arg is missing' '
- git checkout -b usage topic &&
- test_must_fail git rebase 2>error1 &&
- grep "[Uu]sage" error1 &&
- test_must_fail git rebase --abort 2>error2 &&
- grep "No rebase in progress" error2 &&
- test_must_fail git rebase --onto master 2>error3 &&
- grep "[Uu]sage" error3 &&
- ! grep "can.t shift" error3
+ git checkout -b usage topic &&
+ test_must_fail git rebase 2>error1 &&
+ grep "[Uu]sage" error1 &&
+ test_must_fail git rebase --abort 2>error2 &&
+ grep "No rebase in progress" error2 &&
+ test_must_fail git rebase --onto master 2>error3 &&
+ grep "[Uu]sage" error3 &&
+ ! grep "can.t shift" error3
'
test_expect_success 'rebase -q is quiet' '
- git checkout -b quiet topic &&
- git rebase -q master > output.out 2>&1 &&
- test ! -s output.out
+ git checkout -b quiet topic &&
+ git rebase -q master >output.out 2>&1 &&
+ test ! -s output.out
'
test_expect_success 'Rebase a commit that sprinkles CRs in' '
git commit -a -m "end with slash\\" &&
echo >>file1 &&
test_tick &&
+ git commit -a -m "something (\000) that looks like octal" &&
+ echo >>file1 &&
+ test_tick &&
+ git commit -a -m "something (\n) that looks like a newline" &&
+ echo >>file1 &&
+ test_tick &&
git commit -a -m "another commit"
'
test_expect_success 'rebase-i history with funny messages' '
git rev-list A..funny >expect &&
test_tick &&
- FAKE_LINES="1 2" git rebase -i A &&
+ FAKE_LINES="1 2 3 4" git rebase -i A &&
git rev-list A.. >actual &&
test_cmp expect actual
'
--- /dev/null
+#!/bin/sh
+
+test_description='git rebase --continue tests'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+test_expect_success 'setup' '
+ test_commit "commit-new-file-F1" F1 1 &&
+ test_commit "commit-new-file-F2" F2 2 &&
+
+ git checkout -b topic HEAD^ &&
+ test_commit "commit-new-file-F2-on-topic-branch" F2 22 &&
+
+ git checkout master
+'
+
+test_expect_success 'interactive rebase --continue works with touched file' '
+ rm -fr .git/rebase-* &&
+ git reset --hard &&
+ git checkout master &&
+
+ FAKE_LINES="edit 1" git rebase -i HEAD^ &&
+ test-chmtime =-60 F1 &&
+ git rebase --continue
+'
+
+test_expect_success 'non-interactive rebase --continue works with touched file' '
+ rm -fr .git/rebase-* &&
+ git reset --hard &&
+ git checkout master &&
+
+ test_must_fail git rebase --onto master master topic &&
+ echo "Resolved" >F2 &&
+ git add F2 &&
+ test-chmtime =-60 F1 &&
+ git rebase --continue
+'
+
+test_done
echo \"fatal: pathspec 'ignored-file' did not match any files\" | test_cmp - actual
"
-cat >expect <<EOF
+cat >expect.err <<\EOF
The following paths are ignored by one of your .gitignore files:
ignored-file
Use -f if you really want to add them.
fatal: no files added
+EOF
+cat >expect.out <<\EOF
add 'track-this'
EOF
test_expect_success 'git add --dry-run --ignore-missing of non-existing file' '
- test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual 2>&1 &&
- test_cmp expect actual
+ test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual.out 2>actual.err &&
+ test_cmp expect.out actual.out &&
+ test_cmp expect.err actual.err
'
test_done
--- /dev/null
+#!/bin/sh
+
+test_description='diff --relative tests'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ git commit --allow-empty -m empty &&
+ echo content >file1 &&
+ mkdir subdir &&
+ echo other content >subdir/file2 &&
+ git add . &&
+ git commit -m one
+'
+
+check_diff() {
+expect=$1; shift
+cat >expected <<EOF
+diff --git a/$expect b/$expect
+new file mode 100644
+index 0000000..25c05ef
+--- /dev/null
++++ b/$expect
+@@ -0,0 +1 @@
++other content
+EOF
+test_expect_success "-p $*" "
+ git diff -p $* HEAD^ >actual &&
+ test_cmp expected actual
+"
+}
+
+check_stat() {
+expect=$1; shift
+cat >expected <<EOF
+ $expect | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+EOF
+test_expect_success "--stat $*" "
+ git diff --stat $* HEAD^ >actual &&
+ test_cmp expected actual
+"
+}
+
+check_raw() {
+expect=$1; shift
+cat >expected <<EOF
+:000000 100644 0000000000000000000000000000000000000000 25c05ef3639d2d270e7fe765a67668f098092bc5 A $expect
+EOF
+test_expect_success "--raw $*" "
+ git diff --no-abbrev --raw $* HEAD^ >actual &&
+ test_cmp expected actual
+"
+}
+
+for type in diff stat raw; do
+ check_$type file2 --relative=subdir/
+ check_$type file2 --relative=subdir
+ check_$type dir/file2 --relative=sub
+done
+
+test_done
. ./test-lib.sh
-cat >msg <<EOF
-second
-
-Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy
-eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
-voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
-kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem
-ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
-tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
-vero eos et accusam et justo duo dolores et ea rebum.
-
- Duis autem vel eum iriure dolor in hendrerit in vulputate velit
- esse molestie consequat, vel illum dolore eu feugiat nulla facilisis
- at vero eros et accumsan et iusto odio dignissim qui blandit
- praesent luptatum zzril delenit augue duis dolore te feugait nulla
- facilisi.
-
-
-Lorem ipsum dolor sit amet,
-consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
-laoreet dolore magna aliquam erat volutpat.
-
- git
- ---
- +++
-
-Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
-lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure
-dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
-dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
-dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
-feugait nulla facilisi.
-EOF
-
-cat >failmail <<EOF
-From foo@example.com Fri May 23 10:43:49 2008
-From: foo@example.com
-To: bar@example.com
-Subject: Re: [RFC/PATCH] git-foo.sh
-Date: Fri, 23 May 2008 05:23:42 +0200
-
-Sometimes we have to find out that there's nothing left.
-
-EOF
-
-cat >pine <<EOF
-From MAILER-DAEMON Fri May 23 10:43:49 2008
-Date: 23 May 2008 05:23:42 +0200
-From: Mail System Internal Data <MAILER-DAEMON@example.com>
-Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
-Message-ID: <foo-0001@example.com>
-
-This text is part of the internal format of your mail folder, and is not
-a real message. It is created automatically by the mail system software.
-If deleted, important folder data will be lost, and it will be re-created
-with the data reset to initial values.
-
-EOF
-
-echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected
+test_expect_success 'setup: messages' '
+ cat >msg <<-\EOF &&
+ second
+
+ Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy
+ eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
+ voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
+ kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem
+ ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
+ tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
+ vero eos et accusam et justo duo dolores et ea rebum.
+
+ EOF
+ q_to_tab <<-\EOF >>msg &&
+ QDuis autem vel eum iriure dolor in hendrerit in vulputate velit
+ Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis
+ Qat vero eros et accumsan et iusto odio dignissim qui blandit
+ Qpraesent luptatum zzril delenit augue duis dolore te feugait nulla
+ Qfacilisi.
+ EOF
+ cat >>msg <<-\EOF &&
+
+ Lorem ipsum dolor sit amet,
+ consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat.
+
+ git
+ ---
+ +++
+
+ Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure
+ dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
+ dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
+ dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
+ feugait nulla facilisi.
+ EOF
+
+ cat >failmail <<-\EOF &&
+ From foo@example.com Fri May 23 10:43:49 2008
+ From: foo@example.com
+ To: bar@example.com
+ Subject: Re: [RFC/PATCH] git-foo.sh
+ Date: Fri, 23 May 2008 05:23:42 +0200
+
+ Sometimes we have to find out that there'\''s nothing left.
+
+ EOF
+
+ cat >pine <<-\EOF &&
+ From MAILER-DAEMON Fri May 23 10:43:49 2008
+ Date: 23 May 2008 05:23:42 +0200
+ From: Mail System Internal Data <MAILER-DAEMON@example.com>
+ Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
+ Message-ID: <foo-0001@example.com>
+
+ This text is part of the internal format of your mail folder, and is not
+ a real message. It is created automatically by the mail system software.
+ If deleted, important folder data will be lost, and it will be re-created
+ with the data reset to initial values.
+
+ EOF
+
+ signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+'
test_expect_success setup '
echo hello >file &&
test_tick &&
git commit -m first &&
git tag first &&
+
echo world >>file &&
git add file &&
test_tick &&
git commit -s -F msg &&
git tag second &&
+
git format-patch --stdout first >patch1 &&
{
echo "X-Fake-Field: Line One" &&
echo "X-Fake-Field: Line Three" &&
git format-patch --stdout first | sed -e "1d"
} | append_cr >patch1-crlf.eml &&
+
sed -n -e "3,\$p" msg >file &&
git add file &&
test_tick &&
git commit -m third &&
+
git format-patch --stdout first >patch2 &&
+
git checkout -b lorem &&
sed -n -e "11,\$p" msg >file &&
head -n 9 msg >>file &&
test_tick &&
git commit -a -m "moved stuff" &&
+
echo goodbye >another &&
git add another &&
test_tick &&
git commit -m "added another file" &&
- git format-patch --stdout master >lorem-move.patch
-'
-# reset time
-unset test_tick
-test_tick
+ git format-patch --stdout master >lorem-move.patch &&
+
+ git checkout -b rename &&
+ git mv file renamed &&
+ git commit -m "renamed a file" &&
+
+ git format-patch -M --stdout lorem >rename.patch &&
+
+ git reset --soft lorem^ &&
+ git commit -m "renamed a file and added another" &&
+
+ git format-patch -M --stdout lorem^ >rename-add.patch &&
+
+ # reset time
+ unset test_tick &&
+ test_tick
+'
test_expect_success 'am applies patch correctly' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
test_tick &&
git am <patch1 &&
! test -d .git/rebase-apply &&
- test -z "$(git diff second)" &&
+ git diff --exit-code second &&
test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
'
test_expect_success 'am applies patch e-mail not in a mbox' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
git am patch1.eml &&
! test -d .git/rebase-apply &&
- test -z "$(git diff second)" &&
+ git diff --exit-code second &&
test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
'
test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
git am patch1-crlf.eml &&
! test -d .git/rebase-apply &&
- test -z "$(git diff second)" &&
+ git diff --exit-code second &&
test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
'
-GIT_AUTHOR_NAME="Another Thor"
-GIT_AUTHOR_EMAIL="a.thor@example.com"
-GIT_COMMITTER_NAME="Co M Miter"
-GIT_COMMITTER_EMAIL="c.miter@example.com"
-export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
+test_expect_success 'setup: new author and committer' '
+ GIT_AUTHOR_NAME="Another Thor" &&
+ GIT_AUTHOR_EMAIL="a.thor@example.com" &&
+ GIT_COMMITTER_NAME="Co M Miter" &&
+ GIT_COMMITTER_EMAIL="c.miter@example.com" &&
+ export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
+'
compare () {
- test "$(git cat-file commit "$2" | grep "^$1 ")" = \
- "$(git cat-file commit "$3" | grep "^$1 ")"
+ a=$(git cat-file commit "$2" | grep "^$1 ") &&
+ b=$(git cat-file commit "$3" | grep "^$1 ") &&
+ test "$a" = "$b"
}
test_expect_success 'am changes committer and keeps author' '
test_tick &&
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
git am patch2 &&
! test -d .git/rebase-apply &&
test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
- test -z "$(git diff master..HEAD)" &&
- test -z "$(git diff master^..HEAD^)" &&
+ git diff --exit-code master..HEAD &&
+ git diff --exit-code master^..HEAD^ &&
compare author master HEAD &&
compare author master^ HEAD^ &&
test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
'
test_expect_success 'am --signoff adds Signed-off-by: line' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout -b master2 first &&
git am --signoff <patch2 &&
+ printf "%s\n" "$signoff" >expected &&
echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
- test_cmp actual expected &&
+ test_cmp expected actual &&
echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
- test_cmp actual expected
+ test_cmp expected actual
'
test_expect_success 'am stays in branch' '
- test "refs/heads/master2" = "$(git symbolic-ref HEAD)"
+ echo refs/heads/master2 >expected &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expected actual
'
test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
git format-patch --stdout HEAD^ >patch3 &&
sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2," patch3 >patch4
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout HEAD^ &&
git am --signoff patch4 &&
- test "$(git cat-file commit HEAD | grep -c "^Signed-off-by:")" -eq 1
+ git cat-file commit HEAD >actual &&
+ test $(grep -c "^Signed-off-by:" actual) -eq 1
'
test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
- test "$(git rev-parse HEAD)" = "$(git rev-parse master2)"
+ git rev-parse HEAD >expected &&
+ git rev-parse master2 >actual &&
+ test_cmp expected actual
'
test_expect_success 'am --keep really keeps the subject' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout HEAD^ &&
git am --keep patch4 &&
! test -d .git/rebase-apply &&
- git cat-file commit HEAD |
- fgrep "Re: Re: Re: [PATCH 1/5 v2] third"
+ git cat-file commit HEAD >actual &&
+ grep "Re: Re: Re: \[PATCH 1/5 v2\] third" actual
'
test_expect_success 'am -3 falls back to 3-way merge' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout -b lorem2 master2 &&
sed -n -e "3,\$p" msg >file &&
head -n 9 msg >>file &&
git commit -m "copied stuff" &&
git am -3 lorem-move.patch &&
! test -d .git/rebase-apply &&
- test -z "$(git diff lorem)"
+ git diff --exit-code lorem
+'
+
+test_expect_success 'am can rename a file' '
+ grep "^rename from" rename.patch &&
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ git checkout lorem^0 &&
+ git am rename.patch &&
+ ! test -d .git/rebase-apply &&
+ git update-index --refresh &&
+ git diff --exit-code rename
+'
+
+test_expect_success 'am -3 can rename a file' '
+ grep "^rename from" rename.patch &&
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ git checkout lorem^0 &&
+ git am -3 rename.patch &&
+ ! test -d .git/rebase-apply &&
+ git update-index --refresh &&
+ git diff --exit-code rename
+'
+
+test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
+ grep "^rename from" rename-add.patch &&
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ git checkout lorem^0 &&
+ git am -3 rename-add.patch &&
+ ! test -d .git/rebase-apply &&
+ git update-index --refresh &&
+ git diff --exit-code rename
'
test_expect_success 'am -3 -q is quiet' '
+ rm -fr .git/rebase-apply &&
+ git checkout -f lorem2 &&
git reset master2 --hard &&
sed -n -e "3,\$p" msg >file &&
head -n 9 msg >>file &&
git add file &&
test_tick &&
git commit -m "copied stuff" &&
- git am -3 -q lorem-move.patch > output.out 2>&1 &&
+ git am -3 -q lorem-move.patch >output.out 2>&1 &&
! test -s output.out
'
test_expect_success 'am pauses on conflict' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout lorem2^^ &&
test_must_fail git am lorem-move.patch &&
test -d .git/rebase-apply
'
test_expect_success 'am --skip works' '
+ echo goodbye >expected &&
git am --skip &&
! test -d .git/rebase-apply &&
- test -z "$(git diff lorem2^^ -- file)" &&
- test goodbye = "$(cat another)"
+ git diff --exit-code lorem2^^ -- file &&
+ test_cmp expected another
'
test_expect_success 'am --resolved works' '
+ echo goodbye >expected &&
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout lorem2^^ &&
test_must_fail git am lorem-move.patch &&
test -d .git/rebase-apply &&
git add file &&
git am --resolved &&
! test -d .git/rebase-apply &&
- test goodbye = "$(cat another)"
+ test_cmp expected another
'
test_expect_success 'am takes patches from a Pine mailbox' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
cat pine patch1 | git am &&
! test -d .git/rebase-apply &&
- test -z "$(git diff master^..HEAD)"
+ git diff --exit-code master^..HEAD
'
test_expect_success 'am fails on mail without patch' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
test_must_fail git am <failmail &&
- rm -r .git/rebase-apply/
+ git am --abort &&
+ ! test -d .git/rebase-apply
'
test_expect_success 'am fails on empty patch' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
echo "---" >>failmail &&
test_must_fail git am <failmail &&
git am --skip &&
test_expect_success 'am works from stdin in subdirectory' '
rm -fr subdir &&
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
(
mkdir -p subdir &&
cd subdir &&
git am <../patch1
) &&
- test -z "$(git diff second)"
+ git diff --exit-code second
'
test_expect_success 'am works from file (relative path given) in subdirectory' '
rm -fr subdir &&
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
(
mkdir -p subdir &&
cd subdir &&
git am ../patch1
) &&
- test -z "$(git diff second)"
+ git diff --exit-code second
'
test_expect_success 'am works from file (absolute path given) in subdirectory' '
rm -fr subdir &&
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
P=$(pwd) &&
(
cd subdir &&
git am "$P/patch1"
) &&
- test -z "$(git diff second)"
+ git diff --exit-code second
'
test_expect_success 'am --committer-date-is-author-date' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
test_tick &&
git am --committer-date-is-author-date patch1 &&
git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
- at=$(sed -ne "/^author /s/.*> //p" head1) &&
- ct=$(sed -ne "/^committer /s/.*> //p" head1) &&
- test "$at" = "$ct"
+ sed -ne "/^author /s/.*> //p" head1 >at &&
+ sed -ne "/^committer /s/.*> //p" head1 >ct &&
+ test_cmp at ct
'
test_expect_success 'am without --committer-date-is-author-date' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
test_tick &&
git am patch1 &&
git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
- at=$(sed -ne "/^author /s/.*> //p" head1) &&
- ct=$(sed -ne "/^committer /s/.*> //p" head1) &&
- test "$at" != "$ct"
+ sed -ne "/^author /s/.*> //p" head1 >at &&
+ sed -ne "/^committer /s/.*> //p" head1 >ct &&
+ ! test_cmp at ct
'
# This checks for +0000 because TZ is set to UTC and that should
# by test_tick that uses -0700 timezone; if this feature does not
# work, we will see that instead of +0000.
test_expect_success 'am --ignore-date' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
test_tick &&
git am --ignore-date patch1 &&
git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
- at=$(sed -ne "/^author /s/.*> //p" head1) &&
- echo "$at" | grep "+0000"
+ sed -ne "/^author /s/.*> //p" head1 >at &&
+ grep "+0000" at
'
test_expect_success 'am into an unborn branch' '
+ git rev-parse first^{tree} >expected &&
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
rm -fr subdir &&
- mkdir -p subdir &&
+ mkdir subdir &&
git format-patch --numbered-files -o subdir -1 first &&
(
cd subdir &&
git init &&
git am 1
) &&
- result=$(
- cd subdir && git rev-parse HEAD^{tree}
+ (
+ cd subdir &&
+ git rev-parse HEAD^{tree} >../actual
) &&
- test "z$result" = "z$(git rev-parse first^{tree})"
+ test_cmp expected actual
'
test_expect_success 'am newline in subject' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
test_tick &&
- sed -e "s/second/second \\\n foo/" patch1 > patchnl &&
- git am < patchnl > output.out 2>&1 &&
+ sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
+ git am <patchnl >output.out 2>&1 &&
grep "^Applying: second \\\n foo$" output.out
'
test_expect_success 'am -q is quiet' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
git checkout first &&
test_tick &&
- git am -q < patch1 > output.out 2>&1 &&
+ git am -q <patch1 >output.out 2>&1 &&
! test -s output.out
'
'
-test_done
+test_expect_success 'show added path under "--follow -M"' '
+ # This tests for a regression introduced in v1.7.2-rc0~103^2~2
+ test_create_repo regression &&
+ (
+ cd regression &&
+ test_commit needs-another-commit &&
+ test_commit foo.bar &&
+ git log -M --follow -p foo.bar.t &&
+ git log -M --follow --stat foo.bar.t &&
+ git log -M --follow --name-only foo.bar.t
+ )
+'
+test_done
. ./test-lib.sh
-SUBSTFORMAT=%H%n
+SUBSTFORMAT='%H (%h)%n'
test_expect_exists() {
test_expect_success " $1 exists" "test -e $1"
. ./test-lib.sh
+modify () {
+ sed -e "$1" <"$2" >"$2.x" &&
+ mv "$2.x" "$2"
+}
+
D=`pwd`
test_expect_success setup '
test_cmp expect actual
'
+test_expect_success 'setup for detecting upstreamed changes' '
+ mkdir src &&
+ (cd src &&
+ git init &&
+ printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" > stuff &&
+ git add stuff &&
+ git commit -m "Initial revision"
+ ) &&
+ git clone src dst &&
+ (cd src &&
+ modify s/5/43/ stuff &&
+ git commit -a -m "5->43" &&
+ modify s/6/42/ stuff &&
+ git commit -a -m "Make it bigger"
+ ) &&
+ (cd dst &&
+ modify s/5/43/ stuff &&
+ git commit -a -m "Independent discovery of 5->43"
+ )
+'
+
+test_expect_success 'git pull --rebase detects upstreamed changes' '
+ (cd dst &&
+ git pull --rebase &&
+ test -z "$(git ls-files -u)"
+ )
+'
+
+test_expect_success 'setup for avoiding reapplying old patches' '
+ (cd dst &&
+ test_might_fail git rebase --abort &&
+ git reset --hard origin/master
+ ) &&
+ git clone --bare src src-replace.git &&
+ rm -rf src &&
+ mv src-replace.git src &&
+ (cd dst &&
+ modify s/2/22/ stuff &&
+ git commit -a -m "Change 2" &&
+ modify s/3/33/ stuff &&
+ git commit -a -m "Change 3" &&
+ modify s/4/44/ stuff &&
+ git commit -a -m "Change 4" &&
+ git push &&
+
+ modify s/44/55/ stuff &&
+ git commit --amend -a -m "Modified Change 4"
+ )
+'
+
+test_expect_success 'git pull --rebase does not reapply old patches' '
+ (cd dst &&
+ test_must_fail git pull --rebase &&
+ test 1 = $(find .git/rebase-apply -name "000*" | wc -l)
+ )
+'
+
test_done
git bisect reset
'
+test_expect_success 'index-pack and replacements' '
+ git --no-replace-objects rev-list --objects HEAD |
+ git --no-replace-objects pack-objects test- &&
+ git index-pack test-*.pack
+'
+
#
#
test_done
test_expect_success 'use index-filter to move into a subdirectory' '
git branch directorymoved &&
git filter-branch -f --index-filter \
- "git ls-files -s | sed \"s-\\t-&newsubdir/-\" |
+ "git ls-files -s | sed \"s- -&newsubdir/-\" |
GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv \"\$GIT_INDEX_FILE.new\" \"\$GIT_INDEX_FILE\"" directorymoved &&
- test -z "$(git diff HEAD directorymoved:newsubdir)"'
+ git diff --exit-code HEAD directorymoved:newsubdir
+'
test_expect_success 'stops when msg filter fails' '
old=$(git rev-parse HEAD) &&
echo file > file &&
git add file &&
test_tick &&
- git commit -m upstream
+ git commit -m upstream &&
git clone . super &&
git clone super submodule &&
(cd super &&
) &&
mv submodule moved-submodule &&
(cd super &&
- git config -f .gitmodules submodule.submodule.url ../moved-submodule
+ git config -f .gitmodules submodule.submodule.url ../moved-submodule &&
test_tick &&
git commit -a -m moved-submodule
)
test `git rev-parse --verify master:file2` \
= `git rev-parse --verify verify--import-marks:copy-of-file2`'
+test_tick
+mt=$(git hash-object --stdin < /dev/null)
+: >input.blob
+: >marks.exp
+: >tree.exp
+
+cat >input.commit <<EOF
+commit refs/heads/verify--dump-marks
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+test the sparse array dumping routines with exponentially growing marks
+COMMIT
+EOF
+
+i=0
+l=4
+m=6
+n=7
+while test "$i" -lt 27; do
+ cat >>input.blob <<EOF
+blob
+mark :$l
+data 0
+blob
+mark :$m
+data 0
+blob
+mark :$n
+data 0
+EOF
+ echo "M 100644 :$l l$i" >>input.commit
+ echo "M 100644 :$m m$i" >>input.commit
+ echo "M 100644 :$n n$i" >>input.commit
+
+ echo ":$l $mt" >>marks.exp
+ echo ":$m $mt" >>marks.exp
+ echo ":$n $mt" >>marks.exp
+
+ printf "100644 blob $mt\tl$i\n" >>tree.exp
+ printf "100644 blob $mt\tm$i\n" >>tree.exp
+ printf "100644 blob $mt\tn$i\n" >>tree.exp
+
+ l=$(($l + $l))
+ m=$(($m + $m))
+ n=$(($l + $n))
+
+ i=$((1 + $i))
+done
+
+sort tree.exp > tree.exp_s
+
+test_expect_success 'A: export marks with large values' '
+ cat input.blob input.commit | git fast-import --export-marks=marks.large &&
+ git ls-tree refs/heads/verify--dump-marks >tree.out &&
+ test_cmp tree.exp_s tree.out &&
+ test_cmp marks.exp marks.large'
+
###
### series B
###
-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
verbose=t; shift ;;
-q|--q|--qu|--qui|--quie|--quiet)
- quiet=t; shift ;;
+ # Ignore --quiet under a TAP::Harness. Saying how many tests
+ # passed without the ok/not ok details is always an error.
+ test -z "$HARNESS_ACTIVE" && quiet=t; shift ;;
--with-dashes)
with_dashes=t; shift ;;
--no-color)
color=; shift ;;
- --no-python)
- # noop now...
- shift ;;
--va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind)
valgrind=t; verbose=t; shift ;;
--tee)
tr Q '\015'
}
+q_to_tab () {
+ tr Q '\011'
+}
+
append_cr () {
sed -e 's/$/Q/' | tr Q '\015'
}
diff_tree_release_paths(&diff_opts);
/* Go through the new set of filepairing, and see if we find a more interesting one */
+ opt->found_follow = 0;
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
diff_tree_release_paths(opt);
opt->paths[0] = xstrdup(p->one->path);
diff_tree_setup_paths(opt->paths, opt);
+
+ /*
+ * The caller expects us to return a set of vanilla
+ * filepairs to let a later call to diffcore_std()
+ * it makes to sort the renames out (among other
+ * things), but we already have found renames
+ * ourselves; signal diffcore_std() not to muck with
+ * rename information.
+ */
+ opt->found_follow = 1;
break;
}
}
init_tree_desc(&t1, tree1, size1);
init_tree_desc(&t2, tree2, size2);
retval = diff_tree(&t1, &t2, base, opt);
- if (DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) {
+ if (!*base && DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) {
init_tree_desc(&t1, tree1, size1);
init_tree_desc(&t2, tree2, size2);
try_to_follow_renames(&t1, &t2, base, opt);
void update_tree_entry(struct tree_desc *);
void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size);
-/* Helper function that does both of the above and returns true for success */
+/*
+ * Helper function that does both tree_entry_extract() and update_tree_entry()
+ * and returns true for success
+ */
int tree_entry(struct tree_desc *, struct name_entry *);
void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1);
{
int i, ret, bottom;
struct tree_desc t[MAX_UNPACK_TREES];
+ void *buf[MAX_UNPACK_TREES];
struct traverse_info newinfo;
struct name_entry *p;
const unsigned char *sha1 = NULL;
if (dirmask & 1)
sha1 = names[i].sha1;
- fill_tree_descriptor(t+i, sha1);
+ buf[i] = fill_tree_descriptor(t+i, sha1);
}
bottom = switch_cache_bottom(&newinfo);
ret = traverse_trees(n, t, &newinfo);
restore_cache_bottom(&newinfo, bottom);
+
+ for (i = 0; i < n; i++)
+ free(buf[i]);
+
return ret;
}
if (!ret && !size)
ret = malloc(1);
if (!ret)
- die("Out of memory, malloc failed");
+ die("Out of memory, malloc failed (tried to allocate %lu bytes)",
+ (unsigned long)size);
}
#ifdef XMALLOC_POISON
memset(ret, 0xA5, size);