Previously, graph_is_interesting() did not behave quite the same way as
the code in get_revision(). As a result, it would sometimes think
commits were uninteresting, even though get_revision() would return
them. This resulted in incorrect lines in the graph output.
This change creates a get_commit_action() function, which
graph_is_interesting() and simplify_commit() both now use to determine
if a commit will be shown. It is identical to the old simplify_commit()
behavior, except that it never calls rewrite_parents().
This problem was reported by Santi Béjar. The following command
would exhibit the problem before, but now works correctly:
git log --graph --simplify-by-decoration --oneline v1.6.3.3
Previously git graph did not display the output for this command
correctly between f29ac4f and 66996ec, among other places.
Signed-off-by: Adam Simpkins <simpkins@facebook.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Commit de435ac0 changed the behavior of --decorate from printing the
full ref (e.g., "refs/heads/master") to a shorter, more human-readable
version (e.g., just "master"). While this is nice for human readers,
external tools using the output from "git log" may prefer the full
version.
This patch introduces an extension to --decorate to allow the caller to
specify either the short or the full versions.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The option "QUIET" primarily meant "find if we have _any_ difference as
quick as possible and report", which means we often do not even have to
look at blobs if we know the trees are different by looking at the higher
level (e.g. "diff-tree A B"). As a side effect, because there is no point
showing one change that we happened to have found first, it also enables
NO_OUTPUT and EXIT_WITH_STATUS options, making the end result look quiet.
Rename the internal option to QUICK to reflect this better; it also makes
grepping the source tree much easier, as there are other kinds of QUIET
option everywhere.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
For some reason, I ended up doing
git show HEAD~5..
as an odd way of asking for a log. I realize I should just have used "git
log", but at the same time it does make perfect conceptual sense. After
all, you _could_ have done
git show HEAD HEAD~1 HEAD~2 HEAD~3 HEAD~4
and saying "git show HEAD~5.." is pretty natural. It's not like "git show"
only ever showed a single commit (or other object) before either! So
conceptually, giving a commit range is a very sensible operation, even
though you'd traditionally have used "git log" for that.
However, doing that currently results in an error
fatal: object ranges do not make sense when not walking revisions
which admittedly _also_ makes perfect sense - from an internal git
implementation standpoint in 'revision.c'.
However, I think that asking to show a range makes sense to a user, while
saying "object ranges no not make sense when not walking revisions" only
makes sense to a git developer.
So on the whole, of the two different "makes perfect sense" behaviors, I
think I originally picked the wrong one. And quite frankly, I don't really
see anybody actually _depending_ on that error case. So why not change it?
So rather than error out, just turn that non-walking error case into a
"silently turn on walking" instead.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
I do various statistics on git, and one of the things I look at is merges,
because they are often interesting events to count ("how many merges vs
how much 'real development'" kind of statistics). And you can do it with
some fairly straightforward scripting, ie
git rev-list --parents HEAD |
grep ' .* ' |
git diff-tree --always -s --pretty=oneline --stdin |
less -S
will do it.
But I finally got irritated with the fact that we can skip merges with
'--no-merges', but we can't do the trivial reverse operation.
So this just adds a '--merges' flag that _only_ shows merges. Now you can
do the above with just a
git log --merges --pretty=oneline
which is a lot simpler. It also means that we automatically get a lot of
statistics for free, eg
git shortlog -ns --merges
does exactly what you'd want it to do.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This simplifies the logic of rev_compare_tree() by removing a special
case.
It does so by turning the special case of finding a diff to be "all new
files" into a more generic case of "all new" vs "all removed" vs "mixed
changes", so now the code is actually more powerful and more generic, and
the added symmetry actually makes it simpler too.
This makes no changes to any existing behavior, but apart from the
simplification it does make it possible to some day care about whether all
changes were just deletions if we want to. Which we may well want to for
merge handling.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* lt/pack-object-memuse:
show_object(): push path_name() call further down
process_{tree,blob}: show objects without buffering
Conflicts:
builtin-pack-objects.c
builtin-rev-list.c
list-objects.c
list-objects.h
upload-pack.c
In particular, pushing the "path_name()" call _into_ the show() function
would seem to allow
- more clarity into who "owns" the name (ie now when we free the name in
the show_object callback, it's because we generated it ourselves by
calling path_name())
- not calling path_name() at all, either because we don't care about the
name in the first place, or because we are actually happy walking the
linked list of "struct name_path *" and the last component.
Now, I didn't do that latter optimization, because it would require some
more coding, but especially looking at "builtin-pack-objects.c", we really
don't even want the whole pathname, we really would be better off with the
list of path components.
Why? We use that name for two things:
- add_preferred_base_object(), which actually _wants_ to traverse the
path, and now does it by looking for '/' characters!
- for 'name_hash()', which only cares about the last 16 characters of a
name, so again, generating the full name seems to be just unnecessary
work.
Anyway, so I didn't look any closer at those things, but it did convince
me that the "show_object()" calling convention was crazy, and we're
actually better off doing _less_ in list-objects.c, and giving people
access to the internal data structures so that they can decide whether
they want to generate a path-name or not.
This patch does that, and then for people who did use the name (even if
they might do something more clever in the future), it just does the
straightforward "name = path_name(path, component); .. free(name);" thing.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Here's a less trivial thing, and slightly more dubious one.
I was looking at that "struct object_array objects", and wondering why we
do that. I have honestly totally forgotten. Why not just call the "show()"
function as we encounter the objects? Rather than add the objects to the
object_array, and then at the very end going through the array and doing a
'show' on all, just do things more incrementally.
Now, there are possible downsides to this:
- the "buffer using object_array" _can_ in theory result in at least
better I-cache usage (two tight loops rather than one more spread out
one). I don't think this is a real issue, but in theory..
- this _does_ change the order of the objects printed. Instead of doing a
"process_tree(revs, commit->tree, &objects, NULL, "");" in the loop
over the commits (which puts all the root trees _first_ in the object
list, this patch just adds them to the list of pending objects, and
then we'll traverse them in that order (and thus show each root tree
object together with the objects we discover under it)
I _think_ the new ordering actually makes more sense, but the object
ordering is actually a subtle thing when it comes to packing
efficiency, so any change in order is going to have implications for
packing. Good or bad, I dunno.
- There may be some reason why we did it that odd way with the object
array, that I have simply forgotten.
Anyway, now that we don't buffer up the objects before showing them
that may actually result in lower memory usage during that whole
traverse_commit_list() phase.
This is seriously not very deeply tested. It makes sense to me, it seems
to pass all the tests, it looks ok, but...
Does anybody remember why we did that "object_array" thing? It used to be
an "object_list" a long long time ago, but got changed into the array due
to better memory usage patterns (those linked lists of obejcts are
horrible from a memory allocation standpoint). But I wonder why we didn't
do this back then. Maybe there's a reason for it.
Or maybe there _used_ to be a reason, and no longer is.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* jc/maint-1.6.0-keep-pack:
pack-objects: don't loosen objects available in alternate or kept packs
t7700: demonstrate repack flaw which may loosen objects unnecessarily
Remove --kept-pack-only option and associated infrastructure
pack-objects: only repack or loosen objects residing in "local" packs
git-repack.sh: don't use --kept-pack-only option to pack-objects
t7700-repack: add two new tests demonstrating repacking flaws
Conflicts:
t/t7700-repack.sh
This option to pack-objects/rev-list was created to improve the -A and -a
options of repack. It was found to be lacking in that it did not provide
the ability to differentiate between local and non-local kept packs, and
found to be unnecessary since objects residing in local kept packs can be
filtered out by the --honor-pack-keep option.
Signed-off-by: Brandon Casey <casey@nrlssc.navy.mil>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* jc/maint-1.6.0-keep-pack:
is_kept_pack(): final clean-up
Simplify is_kept_pack()
Consolidate ignore_packed logic more
has_sha1_kept_pack(): take "struct rev_info"
has_sha1_pack(): refactor "pretend these packs do not exist" interface
git-repack: resist stray environment variable
Now is_kept_pack() is just a member lookup into a structure, we can write
it as such.
Also rewrite the sole caller of has_sha1_kept_pack() to switch on the
criteria the callee uses (namely, revs->kept_pack_only) between calling
has_sha1_kept_pack() and has_sha1_pack(), so that these two callees do not
have to take a pointer to struct rev_info as an argument.
This removes the header file dependency issue temporarily introduced by
the earlier commit, so we revert changes associated to that as well.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This removes --unpacked=<packfile> parameter from the revision parser, and
rewrites its use in git-repack to pass a single --kept-pack-only option
instead.
The new --kept-pack-only option means just that. When this option is
given, is_kept_pack() that used to say "not on the --unpacked=<packfile>
list" now says "the packfile has corresponding .keep file".
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Its "ignore_packed" parameter always comes from struct rev_info. This
patch makes the function take a pointer to the surrounding structure, so
that the refactoring in the next patch becomes easier to review.
There is an unfortunate header file dependency and the easiest workaround
is to temporarily move the function declaration from cache.h to
revision.h; this will be moved back to cache.h once the function loses
this "ignore_packed" parameter altogether in the later part of the
series.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Most of the callers of this function except only one pass NULL to its last
parameter, ignore_packed.
Introduce has_sha1_kept_pack() function that has the function signature
and the semantics of this function, and convert the sole caller that does
not pass NULL to call this new function.
All other callers and has_sha1_pack() lose the ignore_packed parameter.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
These two are often used together but are too long to type.
Signed-off-by: Nanako Shiraishi <nanako3@lavabit.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Some people prefer to call the pretty-print styles "format", and get
annoyed to see "git log --format=short" fail. Introduce it as a synonym
to --pretty so that both can be used.
Signed-off-by: Nanako Shiraishi <nanako3@lavabit.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
cc0e6c5 (Handle return code of parse_commit in revision machinery,
2007-05-04) attempted to tighten error checking in the revision machinery,
but it wasn't enough. When get_revision_1() was asked for the next commit
to return, it tries to read and simplify the parents of the commit to be
returned, but an error while doing so was silently ignored and reported as
a truncated history to the caller instead.
This resulted in an early end of "git log" output or a pack that lacks
older commits from "git pack-objects", without any error indication in the
exit status from these commands, even though the underlying parse_commit()
issues an error message to the end user.
Note that the codepath in add_parents_list() that paints parents of an
UNINTERESTING commit UNINTERESTING silently ignores the error when
parse_commit() fails; this is deliberate and in line with aeeae1b
(revision traversal: allow UNINTERESTING objects to be missing,
2009-01-27).
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Most of the existing codepaths were meant to treat missing uninteresting
objects to be a silently ignored non-error, but there were a few places
in handle_commit() and add_parents_to_list(), which are two key functions
in the revision traversal machinery, that cared:
- When a tag refers to an object that we do not have, we barfed. We
ignore such a tag if it is painted as UNINTERESTING with this change.
- When digging deeper into the ancestry chain of a commit that is already
painted as UNINTERESTING, in order to paint its parents UNINTERESTING,
we barfed if parse_parent() for a parent commit object failed. We can
ignore such a parent commit object.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When HEAD is detached, --all should list it, too, logically, as a
detached HEAD is by definition a temporary, unnamed branch.
It is especially necessary to list it when garbage collecting, as
the detached HEAD would be trashed.
Noticed by Thomas Rast.
Note that this affects creating bundles with --all; I contend that it
is a good change to add the HEAD, so that cloning from such a bundle
will give you a current branch. However, I had to fix t5701 as it
assumed that --all does not imply HEAD.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* maint:
Documentation: git-svn: fix example for centralized SVN clone
Documentation: fix links to "everyday.html"
revision.c: use proper data type in call to sizeof() within xrealloc
With this, you can simplify history not by the contents of the tree, but
whether a commit has been named (ie it's referred to by some branch or
tag) or not.
This makes it possible to see the relationship between different named
commits, without actually seeing any of the details.
When used with pathspec, you would get the usual view that is limited to
the commits that change the contents of the tree plus commits that are
named.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This will make it easier to do various clever things that don't depend
on the pure tree contents. It also makes the parameter passing much
simpler - the callers doesn't really look at trees anywhere else, and
it's really the function that should look at the low-level details.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
We already support decorating commits by tags or branches that point to
them, but especially when we are looking at multiple branches together,
we sometimes want to see _how_ we reached a particular commit.
We can abuse the '->util' field in the commit to keep track of that as
we walk the commit lists, and get a reasonably useful view into which
branch or tag first reaches that commit.
Of course, if the commit is reachable through multiple sources (which is
common), our particular choice of "first" reachable is entirely random
and depends on the particular path we happened to follow.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* jc/maint-log-grep:
log --author/--committer: really match only with name part
diff --cumulative is a sub-option of --dirstat
bash completion: Hide more plumbing commands
When we tried to find commits done by AUTHOR, the first implementation
tried to pattern match a line with "^author .*AUTHOR", which later was
enhanced to strip leading caret and look for "^author AUTHOR" when the
search pattern was anchored at the left end (i.e. --author="^AUTHOR").
This had a few problems:
* When looking for fixed strings (e.g. "git log -F --author=x --grep=y"),
the regexp internally used "^author .*x" would never match anything;
* To match at the end (e.g. "git log --author='google.com>$'"), the
generated regexp has to also match the trailing timestamp part the
commit header lines have. Also, in order to determine if the '$' at
the end means "match at the end of the line" or just a literal dollar
sign (probably backslash-quoted), we would need to parse the regexp
ourselves.
An earlier alternative tried to make sure that a line matches "^author "
(to limit by field name) and the user supplied pattern at the same time.
While it solved the -F problem by introducing a special override for
matching the "^author ", it did not solve the trailing timestamp nor tail
match problem. It also would have matched every commit if --author=author
was asked for, not because the author's email part had this string, but
because every commit header line that talks about the author begins with
that field name, regardleses of who wrote it.
Instead of piling more hacks on top of hacks, this rethinks the grep
machinery that is used to look for strings in the commit header, and makes
sure that (1) field name matches literally at the beginning of the line,
followed by a SP, and (2) the user supplied pattern is matched against the
remainder of the line, excluding the trailing timestamp data.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* tr/filter-branch:
revision --simplify-merges: make it a no-op without pathspec
revision --simplify-merges: do not leave commits unprocessed
revision --simplify-merges: use decoration instead of commit->util field
Documentation: rev-list-options: move --simplify-merges documentation
filter-branch: use --simplify-merges
filter-branch: fix ref rewriting with --subdirectory-filter
filter-branch: Extend test to show rewriting bug
Topo-sort before --simplify-merges
revision traversal: show full history with merge simplification
revision.c: whitespace fix
--reverse did not interact well with --parents, as the included test
case shows: in a history like
A--B.
\ \
`C--M--D
the command
git rev-list --reverse --parents --full-history HEAD
erroneously lists D as having no parents at all. (Without --reverse,
it correctly lists M.)
This is caused by the machinery driving --reverse: it first grabs all
commits through the normal routines, then runs them through the same
routines again, effectively simplifying them twice.
Fix this by moving the --reverse one level up, into get_revision().
This way we can cleanly grab all commits via the normal calls, then
just pop them off the list one by one without interfering with
get_revision_internal().
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This has been broken in v1.6.0 due to the reorganization of
the revision option parsing code. The "-i" is completely
ignored, but works fine in "git log --grep -i".
What happens is that the code for "-i" looks for
revs->grep_filter; if it is NULL, we do nothing, since there
are no grep filters. But that is obviously not correct,
since we want it to influence the later --grep option. Doing
it the other way around works, since "-i" just impacts the
existing grep_filter option.
Instead, we now always initialize the grep_filter member and
just fill in options and patterns as we get them. This means
that we can no longer check grep_filter for NULL, but
instead must check the pattern list to see if we have any
actual patterns.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When we are not pruning there is no reason to run the merge
simplification.
Also avoid running topo-order sort twice.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When we still do not know how parents of a commit simplify to, we should
defer processing of the commit, not discard it.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The users of revision walking machinery may want to use the util pointer
for their own use. Use decoration to hold the data needed during merge
simplification instead.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This makes the algorithm more honest about what it is doing.
We start from an already limited, topo-sorted list, and postprocess
it by simplifying the irrelevant merges away.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The --full-history traversal keeps all merges in addition to non-merge
commits that touch paths in the given pathspec. This is useful to view
both sides of a merge in a topology like this:
A---M---o
/ /
---O---B
even when A and B makes identical change to the given paths. The revision
traversal without --full-history aims to come up with the simplest history
to explain the final state of the tree, and one of the side branches can
be pruned away.
The behaviour to keep all merges however is inconvenient if neither A nor
B touches the paths we are interested in. --full-history reduces the
topology to:
---O---M---o
in such a case, without removing M.
This adds a post processing phase on top of --full-history traversal to
remove needless merges from the resulting history.
The idea is to compute, for each commit in the "full history" result set,
the commit that should replace it in the simplified history. The commit
to replace it in the final history is determined as follows:
* In any case, we first figure out the replacement commits of parents of
the commit we are looking at. The commit we are looking at is
rewritten as if the replacement commits of its original parents are its
parents. While doing so, we reduce the redundant parents from the
rewritten parent list by not just removing the identical ones, but also
removing a parent that is an ancestor of another parent.
* After the above parent simplification, if the commit is a root commit,
an UNINTERESTING commit, a merge commit, or modifies the paths we are
interested in, then the replacement commit of the commit is itself. In
other words, such a commit is not dropped from the final result.
The first point above essentially means that the history is rewritten in
the bottom up direction. We can rewrite the parent list of a commit only
after we know how all of its parents are rewritten. This means that the
processing needs to happen on the full history (i.e. after limit_list()).
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Commands which use parse_options() but also call setup_revisions()
must do their parsing in a two step process:
1. first, they parse all options. Anything unknown goes to
parse_revision_opt() (which calls handle_revision_opt), which
may claim the option or say "I don't recognize this"
2. the non-option remainder goes to setup_revisions() to
actually get turned into revisions
Some revision options are "non-options" in that they must be
parsed in order with their revision counterparts in
setup_revisions(). For example, "--all" functions as a
pseudo-option expanding to all refs, and "--no-walk" affects refs
after it on the command line, but not before. The revision option
parser in step 1 recognizes such options and sets them aside for
later parsing by setup_revisions().
However, the return value used from handle_revision_opt indicated
"I didn't recognize this", which was wrong. It did, and it took
appropriate action (even though that action was just deferring it
for later parsing). Thus it should return "yes, I recognized
this."
Previously, these pseudo-options generated an error when used with
parse_options parsers (currently just blame and shortlog). With
this patch, they should work fine, enabling things like "git
shortlog --all".
Signed-off-by: Jeff King <peff@peff.net>
Acked-By: Pierre Habouzit <madcoder@debian.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* maint:
Start preparing 1.5.6.4 release notes
git fetch-pack: do not complain about "no common commits" in an empty repo
rebase-i: keep old parents when preserving merges
t7600-merge: Use test_expect_failure to test option parsing
Fix buffer overflow in prepare_attr_stack
Fix buffer overflow in git diff
Fix buffer overflow in git-grep
git-cvsserver: fix call to nonexistant cleanupWorkDir()
Documentation/git-cherry-pick.txt et al.: Fix misleading -n description
Conflicts:
RelNotes
If PATH_MAX on your system is smaller than a path stored, it may cause
buffer overflow and stack corruption in diff_addremove() and diff_change()
functions when running git-diff
Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* ph/parseopt-step-blame:
revisions: refactor handle_revision_opt into parse_revision_opt.
git-shortlog: migrate to parse-options partially.
git-blame: fix lapsus
git-blame: migrate to incremental parse-option [2/2]
git-blame: migrate to incremental parse-option [1/2]
revisions: split handle_revision_opt() from setup_revisions()
parse-opt: add PARSE_OPT_KEEP_ARGV0 parser option.
parse-opt: fake short strings for callers to believe in.
parse-opt: do not print errors on unknown options, return -2 intead.
parse-opt: create parse_options_step.
parse-opt: Export a non NORETURN usage dumper.
parse-opt: have parse_options_{start,end}.
git-blame --reverse
builtin-blame.c: allow more than 16 parents
builtin-blame.c: move prepare_final() into a separate function.
rev-list --children
revision traversal: --children option
Parent commits are usually older than their children. Thus,
on each iteration of the loop in rewrite_one, add_parents_to_list
traverses all commits previously processed by the loop.
It performs very poorly in case of very long rewrite chains.
Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
It seems we're using handle_revision_opt the same way each time, have a
wrapper around it that does the 9-liner we copy each time instead.
handle_revision_opt can be static in the module for now, it's always
possible to make it public again if needed.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Add two fields to struct rev_info:
- .def to store --default argument; and
- .show_merge 1-bit field.
handle_revision_opt() is able to deal with any revision option, and
consumes them, and leaves revision arguments or pseudo arguments
(like --all, --not, ...) in place.
For now setup_revisions() does a pass of handle_revision_opt() again
so that code not using it in a parse-opt parser still work the same.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Reading rev-list parameters from the command line can be reused by
commands other than rev-list. Move this function to more "library-ish"
place to promote code reuse.
Signed-off-by: Adam Brewster <asb@bu.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Now get_revision() sorts the boundary commits when topo_order is set.
Since sort_in_topological_order() takes a struct commit_list, it first
places the boundary commits into revs->commits.
Signed-off-by: Adam Simpkins <adam@adamsimpkins.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Previously the graphing API wasn't aware of the revs->boundary flag, and
it always assumed that commits marked UNINTERESTING would not be
displayed. As a result, the boundary commits were printed at the end of
the log output, but they didn't have any branch lines connecting them to
their children in the graph.
There was also another bug in the get_revision() code that caused
graph_update() to be called twice on the first boundary commit. This
caused the graph API to think that a commit had been skipped, and print
a "..." line in the output.
Signed-off-by: Adam Simpkins <adam@adamsimpkins.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
With the --graph option, the graph already outputs 'o' instead of '*'
for boundary commits. Make it emit '<' or '>' when --left-right is
specified.
(This change also disables the '^' prefix for UNINTERESTING commits.
The graph code currently doesn't print anything special for these
commits, since it assumes no UNINTERESTING, non-BOUNDARY commits are
displayed. This is potentially a bug if UNINTERESTING non-BOUNDARY
commits can actually be displayed via some code path.)
[jc: squashed the left-right change from Dscho and Adam's fixup into one]
Signed-off-by: Adam Simpkins <adam@adamsimpkins.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In add_parents_to_list, if any parent of a revision had already been
SEEN, the current code would continue with the next parent, skipping
the test for --first-parent. This patch inverts the test for SEEN so
that the test for --first-parent is always performed.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This new option causes a text-based representation of the history to be
printed to the left of the normal output.
Signed-off-by: Adam Simpkins <adam@adamsimpkins.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This change allows parent rewriting to be performed without causing
the log and rev-list commands to print the parents.
Signed-off-by: Adam Simpkins <adam@adamsimpkins.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The purpose of --first-parent is to view the tree without looking at
side branche. This is accomplished by pretending there are no other
parents than the first parent when encountering a merge.
The current code marks the other parents as seen, which means that the tree
traversal will behave differently depending on the order merges are handled.
When a fast forward is artificially recorded as a merge,
-----
/ \
D---E---F---G master
the current first-parent code considers E to be seen and stops the
traversal after showing G and F.
Signed-off-by: Stephen R. van den Berg <srb@cuci.nl>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This adds a new --children option to the revision machinery. In addition
to the list of parents, child commits of each commit are computed and
stored as a decoration to each commit.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* maint-1.5.4:
bisect: fix bad rev checking in "git bisect good"
revision.c: make --date-order overriddable
Fix section about backdating tags in the git-tag docs
Document option --only of git commit
Documentation/git-request-pull: Fixed a typo ("send" -> "end")
Jan Engelhardt noticed that while --topo-order can be overridden by a
subsequent --date-order, the reverse was not possible. That's because
setup_revisions() failed to set revs->lifo properly.
Signed-off-by: Michele Ballabio <barra_cuda@katamail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This attached patch introduces a single bit "use_terminator" in "struct
rev_info", which is normally false (i.e. most formats use separator
semantics) but by flipping it to true, you can ask for terminator
semantics just like oneline format does.
The function get_commit_format(), which is what parses "--pretty=" option,
now takes a pointer to "struct rev_info" and updates its commit_format and
use_terminator fields. It used to return the value of type "enum
cmit_fmt", but all the callers assigned it to rev->commit_format.
There are only two cases the code turns use_terminator on. Obviously, the
traditional oneline format (--pretty=oneline) is one of them, and the new
case is --pretty=tformat:... that acts like --pretty=format:... but flips
the bit on.
With this, "--pretty=tformat:%H %s" acts like --pretty=oneline.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The revision limiter uses the commit date to decide when it has seen
enough commits to finalize the revision list, but that can get confused
if there are incorrect dates far in the past on some commits.
This makes the logic a bit more robust by
- we always walk an extra SLOP commits from the source list even if we
decide that the source list is probably all done (unless the source is
entirely empty, of course, because then we really can't do anything at
all)
- we keep track of the date of the last commit we added to the
destination list (this will *generally* be the oldest entry we've seen
so far)
- we compare that with the youngest entry (the first one) of the source
list, and if the destination is older than the source, we know we want
to look at the source.
which causes occasional date mishaps to be handled cleanly.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
These flags are already known to rev-parse and have the same meaning.
This patch allows to run gitk as follows:
gitk --branches --not --remotes
to show only your local work.
Signed-off-by: Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Add support for -F | --fixed-strings option to "git log --grep"
and friends: "git log --author", "git log --committer=<pattern>".
Code is based on implementation of this option in "git grep".
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
As these functions are directly called with the result
from lookup_tree/blob, they must handle NULL.
Signed-off-by: Martin Koegler <mkoegler@auto.tuwien.ac.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
It's really not very easy to visualize the commit walker, because - on
purpose - it obvously doesn't show the uninteresting commits!
This adds a "--show-all" flag to the revision walker, which will make
it show uninteresting commits too, and they'll have a '^' in front of
them (it also fixes a logic error for !verbose_header for boundary
commits - we should show the '-' even if left_right isn't shown).
A separate patch to gitk to teach it the new '^' was sent
to paulus. With the change in place, it actually is interesting
even for the cases that git doesn't have any problems with, ie
for the kernel you can do:
gitk -d --show-all v2.6.24..
and you see just how far down it has to parse things to see it all. The
use of "-d" is a good idea, since the date-ordered toposort is much better
at showing why it goes deep down (ie the date of some of those commits
after 2.6.24 is much older, because they were merged from trees that
weren't rebased).
So I think this is a useful feature even for non-debugging - just to
visualize what git does internally more.
When it actually breaks out due to the "everybody_uninteresting()"
case, it adds the uninteresting commits (both the one it's looking at
now, and the list of pending ones) to the list
This way, we really list *all* the commits we've looked at.
Because we now end up listing commits we may not even have been parsed
at all "show_log" and "show_commit" need to protect against commits
that don't have a commit buffer entry.
That second part is debatable just how it should work. Maybe we shouldn't
show such entries at all (with this patch those entries do get shown, they
just don't get any message shown with them). But I think this is a useful
case.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This allows the --relative option to say which subdirectory to
pretend to be in, so that in a bare repository, you can say:
$ git log --relative=drivers/ v2.6.20..v2.6.22 -- drivers/scsi/
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This adds --relative option to the diff family. When you start
from a subdirectory:
$ git diff --relative
shows only the diff that is inside your current subdirectory,
and without $prefix part. People who usually live in
subdirectories may like it.
There are a few things I should also mention about the change:
- This works not just with diff but also works with the log
family of commands, but the history pruning is not affected.
In other words, if you go to a subdirectory, you can say:
$ git log --relative -p
but it will show the log message even for commits that do not
touch the current directory. You can limit it by giving
pathspec yourself:
$ git log --relative -p .
This originally was not a conscious design choice, but we
have a way to affect diff pathspec and pruning pathspec
independently. IOW "git log --full-diff -p ." tells it to
prune history to commits that affect the current subdirectory
but show the changes with full context. I think it makes
more sense to leave pruning independent from --relative than
the obvious alternative of always pruning with the current
subdirectory, which would break the symmetry.
- Because this works also with the log family, you could
format-patch a single change, limiting the effect to your
subdirectory, like so:
$ cd gitk-git
$ git format-patch -1 --relative 911f1eb
But because that is a special purpose usage, this option will
never become the default, with or without repository or user
preference configuration. The risk of producing a partial
patch and sending it out by mistake is too great if we did
so.
- This is inherently incompatible with --no-index, which is a
bolted-on hack that does not have much to do with git
itself. I didn't bother checking and erroring out on the
combined use of the options, but probably I should.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In commit b7bb760d5e (Fix revision
log diff setup, avoid unnecessary diff generation) an optimization was
made to avoid unnecessary diff generation. This was partly fixed in
99516e35d0 (Fix embarrassing "git log
--follow" bug). The '--diff-filter' option also needs the diff machinery
in action.
Signed-off-by: Arjen Laarhoven <arjen@yaph.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Instead of warning the user that it is expecting git log output from
the standard input (and waiting for the user to type the log from
the keyboard, which is a silly thing to do), default to traverse from
HEAD when there is no rev parameter given and the standard input is
a tty.
This factors out a useful helper "add_head()" from builtin-diff.c to a
more appropriate place revision.c while renaming it to more descriptive
name add_head_to_pending(), as that is what the function is about.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* lt/rev-list-interactive:
Fix parent rewriting in --early-output
revision walker: mini clean-up
Enhance --early-output format
Add "--early-output" log flag for interactive GUI use
Simplify topo-sort logic
We cannot tell a node that has been checked and found not to be
interesting (which does not have the TREECHANGE flag) from a
node that hasn't been checked if it is interesting or not,
without relying on something else, such as object->parsed.
But an object can get the "parsed" flag for other reasons.
Which means that "TREECHANGE" has the wrong polarity.
This changes the way how the path pruning logic marks an
uninteresting commits. From now on, we consider a commit
interesting by default, and explicitly mark the ones we decided
to prune. The flag is renamed to "TREESAME".
Then, this fixes the logic to show the early output with
incomplete pruning. It basically says "a commit that has
TREESAME set is kind-of-UNINTERESTING", but obviously in a
different way than an outright UNINTERESTING commit. Until we
parse and examine enough parents to determine if a commit
becomes surely "kind-of-UNINTERESTING", we avoid rewriting
the ancestry so that later rounds can fix things up.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The function mark_tree_uninteresting() assumed that the tree entries
are blob when they are not trees. This is not so. Since we do
not traverse into submodules (yet), the gitlinks should be ignored.
In general, we should try to start moving away from using the
"S_ISLNK()" like things for internal git state. It was a mistake to
just assume the numbers all were same across all systems in the first
place. This implementation converts to the "object_type", and then
uses a case statement.
Noticed by Ilari on IRC.
Test script taken from an earlier version by Dscho.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
reverse_diff was a bit-value in disguise, it's merged in the flags now.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This removes the unnecessary indirection of "revs->prune_fn",
since that function is always the same one (or NULL), and there
is in fact not even an abstraction reason to make it a function
(i.e. its not called from some other file and doesn't allow us
to keep the function itself static or anything like that).
It then just replaces it with a bit that says "prune or not",
and if not pruning, every commit gets TREECHANGE.
That in turn means that
- if (!revs->prune_fn || (flags & TREECHANGE))
- if (revs->prune_fn && !(flags & TREECHANGE))
just become
- if (flags & TREECHANGE)
- if (!(flags & TREECHANGE))
respectively.
Together with adding the "single_parent()" helper function, the "complex"
conditional now becomes
if (!(flags & TREECHANGE) && rev->dense && single_parent(commit))
continue;
Also indirection of "revs->dense" checking is thrown away the
same way, because TREECHANGE bit is set appropriately now.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This makes --early-output a bit more advanced, and actually makes it
generate multiple "Final output:" headers as it updates things
asynchronously. I realize that the "Final output:" line is now illogical,
since it's not really final until it also says "done", but
It now _always_ generates a "Final output:" header in front of any commit
list, and that output header gives you a *guess* at the maximum number of
commits available. However, it should be noted that the guess can be
completely off: I do a reasonable job estimating it, but it is not meant
to be exact.
So what happens is that you may get output like this:
- at 0.1 seconds:
Final output: 2 incomplete
.. 2 commits listed ..
- half a second later:
Final output: 33 incomplete
.. 33 commits listed ..
- another half a second after that:
Final output: 71 incomplete
.. 71 commits listed ..
- another half second later:
Final output: 136 incomplete
.. 100 commits listed: we hit the --early-output limit, and
.. will only output 100 commits, and after this you'll not
.. see an "incomplete" report any more since you got as much
.. early output as you asked for!
- .. and then finally:
Final output: 73106 done
.. all the commits ..
The above is a real-life scenario on my current kernel tree after having
flushed all the caches.
Tested with the experimental gitk patch that Paul sent out, and by looking
at the actual log output (and verifying that my commit count guesses
actually match real life fairly well).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This adds support for "--early-output[=n]" as a flag to the "git log"
family of commands. This allows GUI programs to state that they want to
get some output early, in order to be able to show at least something
quickly, even if the full output may take longer to generate.
If no count is specified, a default count of a hundred commits will be
used, although the actual numbr of commits output may be smaller
depending on how many commits were actually found in the first tenth of
a second (or if *everything* was found before that, in which case no
early output will be provided, and only the final list is made
available).
When the full list is generated, there will be a "Final output:" string
prepended to it, regardless of whether any early commits were shown or
not, so that the consumer can always know the difference between early
output and the final list.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
.. by not using quite so much indirection.
This currently grows the "struct commit" a bit, which could be avoided by
using a union for "util" and "indegree" (the topo-sort used to use "util"
anyway, so you cannot use them together), but for now the goal of this was
to simplify, not optimize.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
It turns out that I completely broke "git log --follow" with my recent
patch to revision.c ("Fix revision log diff setup, avoid unnecessary diff
generation", commit b7bb760d5e).
Why? Because --follow obviously requires the diff machinery to function,
exactly the same way pickaxe does.
So everybody is away right now, but considering that nobody even noticed
this bug, I don't think it matters. But for the record, here's the trivial
one-liner fix (well, two, since I also fixed the comment).
Because of the nature of the bug, if you ask for patches when following
(which is one of the things I normally do), the bug is hidden, because
then the request for diff output will automatically also enable the diffs
themselves.
So while "git log --follow <filename>" didn't work, adding a "-p"
magically made it work again even without this fix.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Factor out the code to parse --date=<format> parameter to revision
walkers into a separate function, parse_date_format(). This function
is passed a string and converts it to an enum date_format:
- "relative" => DATE_RELATIVE
- "iso8601" or "iso" => DATE_ISO8601
- "rfc2822" => DATE_RFC2822
- "short" => DATE_SHORT
- "local" => DATE_LOCAL
- "default" => DATE_NORMAL
In the event that none of these strings is found, the function die()s.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
We used to incorrectly start calculating diffs whenever any argument but
'-z' was recognized by the diff options parsing. That was bogus, since not
all arguments result in diffs being needed, so we just waste a lot of time
and effort on calculating diffs that don't matter.
This actually also fixes another bug in "git log". Try this:
git log -C
and notice how it prints an extra empty line in between log entries, even
though it never prints the actual diff (because we didn't ask for any diff
format, so the diff machinery never prints anything).
With this patch, that bogus empty line is gone, because "revs->diff" is
never set. So this isn't just a "wasted time and effort" issue, it's also
a slight semantic fix.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>