From: Jay Soffian <jaysoffian@gmail.com>
To: git@vger.kernel.org
Cc: Jay Soffian <jaysoffian@gmail.com>
Subject: [RFC/PATCH] rev-list: new --cherry-pick=loose option
Date: Mon, 21 Feb 2011 14:49:29 -0500 [thread overview]
Message-ID: <1298317769-65830-1-git-send-email-jaysoffian@gmail.com> (raw)
rev-list --cherry-pick may be used in combination with the
symmetric difference operator (A...B) to squelch showing commits
which are identical in content.
Sometimes this is too strict of a test, for example if the
cherry-picked commits required conflict resolution, altering
their patch-ids. However, it is still useful to be able to squelch
such commits as they need not be cherry-picked again.
Using --cherry-pick=loose tells git to ignore the patch content
and instead examine its metadata. Specifically, commits with
identical authorship (name and timestamp) and subject are not
shown in the output.
Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
This is a bit of a hack just to stimulate conversation. My use
case for this is that I'm cherry-picking commits from a release branch
onto a development branch. (I cannot use a different branching strategy
that would allow me to merge instead.) Sometimes those cherry-picks require
conflict resolution. The current --cherry-pick behavior requires that I
maintain (externally to git) a list of commits which have already been
cherry-picked.
So I started experimenting with a wrapper around rev-list A...B that
looks at commit metadata to determine what's been cherry-picked and
what not, and it works quite well for me.
The functionality in this patch would let me get rid of that wrapper.
Thoughts?
patch-ids.c | 23 +++++++++++++++++++++--
patch-ids.h | 2 +-
revision.c | 9 +++++++++
revision.h | 1 +
4 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/patch-ids.c b/patch-ids.c
index 5717257..6a1f3e3 100644
--- a/patch-ids.c
+++ b/patch-ids.c
@@ -16,6 +16,20 @@ static int commit_patch_id(struct commit *commit, struct diff_options *options,
return diff_flush_patch_id(options, sha1);
}
+static int commit_patch_id_loose(struct commit *commit, unsigned char *sha1)
+{
+ git_SHA_CTX ctx;
+ struct strbuf buf = STRBUF_INIT;
+ struct pretty_print_context pctx = {0};
+
+ git_SHA1_Init(&ctx);
+ format_commit_message(commit, "%an %ae %at %s", &buf, &pctx);
+ git_SHA1_Update(&ctx, buf.buf, buf.len);
+ strbuf_release(&buf);
+ git_SHA1_Final(sha1, &ctx);
+ return 0;
+}
+
static const unsigned char *patch_id_access(size_t index, void *table)
{
struct patch_id **id_table = table;
@@ -65,8 +79,13 @@ static struct patch_id *add_commit(struct commit *commit,
unsigned char sha1[20];
int pos;
- if (commit_patch_id(commit, &ids->diffopts, sha1))
- return NULL;
+ if (ids->loose) {
+ if (commit_patch_id_loose(commit, sha1))
+ return NULL;
+ } else {
+ if (commit_patch_id(commit, &ids->diffopts, sha1))
+ return NULL;
+ }
pos = patch_pos(ids->table, ids->nr, sha1);
if (0 <= pos)
return ids->table[pos];
diff --git a/patch-ids.h b/patch-ids.h
index c8c7ca1..f54b0ee 100644
--- a/patch-ids.h
+++ b/patch-ids.h
@@ -8,7 +8,7 @@ struct patch_id {
struct patch_ids {
struct diff_options diffopts;
- int nr, alloc;
+ int nr, alloc, loose;
struct patch_id **table;
struct patch_id_bucket *patches;
};
diff --git a/revision.c b/revision.c
index 7b9eaef..6dbbf5d 100644
--- a/revision.c
+++ b/revision.c
@@ -558,6 +558,8 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
ids.diffopts.paths = revs->diffopt.paths;
ids.diffopts.pathlens = revs->diffopt.pathlens;
}
+ if (revs->cherry_pick_loose)
+ ids.loose = 1;
/* Compute patch-ids for one side */
for (p = list; p; p = p->next) {
@@ -1268,6 +1270,13 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if (!strcmp(arg, "--cherry-pick")) {
revs->cherry_pick = 1;
revs->limited = 1;
+ } else if (!prefixcmp(arg, "--cherry-pick=")) {
+ revs->cherry_pick = 1;
+ revs->limited = 1;
+ if (!strcmp(arg+14, "loose"))
+ revs->cherry_pick_loose = 1;
+ else if (strcmp(arg+14, "strict"))
+ return error("bad --cherry-pick argument");
} else if (!strcmp(arg, "--objects")) {
revs->tag_objects = 1;
revs->tree_objects = 1;
diff --git a/revision.h b/revision.h
index 05659c6..3f94b27 100644
--- a/revision.h
+++ b/revision.h
@@ -66,6 +66,7 @@ struct rev_info {
reverse:1,
reverse_output_stage:1,
cherry_pick:1,
+ cherry_pick_loose:1,
bisect:1,
ancestry_path:1,
first_parent_only:1;
--
1.7.4.1.51.g2cc0c.dirty
next reply other threads:[~2011-02-21 19:49 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-21 19:49 Jay Soffian [this message]
2011-02-22 0:16 ` [RFC/PATCH] rev-list: new --cherry-pick=loose option Junio C Hamano
2011-02-22 2:54 ` Jay Soffian
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1298317769-65830-1-git-send-email-jaysoffian@gmail.com \
--to=jaysoffian@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).