From: Junio C Hamano <gitster@pobox.com>
To: "Martin Langhoff" <martin.langhoff@gmail.com>
Cc: "Jeff King" <peff@peff.net>, "Steffen Prohaska" <prohaska@zib.de>,
"Git Mailing List" <git@vger.kernel.org>,
Daniel Barkalow <barkalow@iabervon.org>,
Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [RFC] checkout to notice forks (Re: Minor annoyance with git push)
Date: Sat, 16 Feb 2008 17:08:22 -0800 [thread overview]
Message-ID: <7vfxvs75kp.fsf_-_@gitster.siamese.dyndns.org> (raw)
In-Reply-To: <7vwspd5z1d.fsf@gitster.siamese.dyndns.org> (Junio C. Hamano's message of "Sat, 09 Feb 2008 18:24:30 -0800")
Junio C Hamano <gitster@pobox.com> writes:
> Perhaps making "git-checkout" to notice this and offer (or
> suggest) fast-forwarding at that point may be safer and make
> more sense. You cannot grow your local branch unless you check
> them out, and your remote tracking will keep growing without the
> auto-ff you are suggesting, so it is not like people will lose
> anchoring point to compare between branches if we do not
> auto-ff.
So I did this.
When you are switching to a branch that is marked to merge from
somewhere else, e.g. when you have:
[branch "next"]
remote = upstream
merge = refs/heads/next
[remote "upstream"]
url = ...
fetch = refs/heads/*:refs/remotes/linus/*
and you say "git checkout next", then after we switch the branch
we check the upstream (in this case, refs/remotes/linus/next)
and our branch, and:
(1) if they match, nothing happens;
(2) if you are ahead (i.e. the upstream is a strict ancestor
of you), one line message tells you so;
(3) otherwise, you are either behind or you and the upstream
have forked. One line message will tell you which and
then you will see a "log --pretty=oneline --left-right".
We could enhance this with an option that tells the command to
check if there is no local change, and automatically fast
forward when you are truly behind. But I ripped out that change
because I was unsure what the right way should be to allow users
to control it (issues include that checkout should not become
automatically interactive).
This is hot off the press and I know it tends to be a bit too
loud. It is based on Daniel's "git checkout in C" with Dscho's
lock_file fix.
---
builtin-checkout.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 136 insertions(+), 0 deletions(-)
diff --git a/builtin-checkout.c b/builtin-checkout.c
index 59a0ef4..9370ba0 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -12,6 +12,7 @@
#include "branch.h"
#include "diff.h"
#include "revision.h"
+#include "remote.h"
static const char * const checkout_usage[] = {
"git checkout [options] <branch>",
@@ -290,6 +291,139 @@ static int merge_working_tree(struct checkout_opts *opts,
return 0;
}
+/*
+ * We really should allow cb_data... Yuck
+ */
+static const char *branch_name;
+static int branch_name_len;
+static char *found_remote;
+static char *found_merge;
+static int read_branch_config(const char *var, const char *value)
+{
+ const char *name;
+ if (prefixcmp(var, "branch."))
+ return 0; /* not ours */
+ name = var + strlen("branch.");
+ if (strncmp(name, branch_name, branch_name_len) ||
+ name[branch_name_len] != '.')
+ return 0; /* not ours either */
+ if (!strcmp(name + branch_name_len, ".remote")) {
+ /*
+ * Yeah, I know Christian's clean-up should
+ * be used here, but the topic is based on an
+ * older fork point.
+ */
+ if (!value)
+ return error("'%s' not string", var);
+ found_remote = xstrdup(value);
+ return 0;
+ }
+ if (!strcmp(name + branch_name_len, ".merge")) {
+ if (!value)
+ return error("'%s' not string", var);
+ found_merge = xstrdup(value);
+ return 0;
+ }
+ return 0; /* not ours */
+}
+
+static int find_build_base(const char *ours, char **base)
+{
+ struct remote *remote;
+ struct refspec spec;
+
+ *base = NULL;
+
+ branch_name = ours + strlen("refs/heads/");
+ branch_name_len = strlen(branch_name);
+ found_remote = NULL;
+ found_merge = NULL;
+ git_config(read_branch_config);
+
+ if (!found_remote || !found_merge) {
+ cleanup:
+ free(found_remote);
+ free(found_merge);
+ return 0;
+ }
+
+ remote = remote_get(found_remote);
+ memset(&spec, 0, sizeof(spec));
+ spec.src = found_merge;
+ if (remote_find_tracking(remote, &spec))
+ goto cleanup;
+ *base = spec.dst;
+ return 1;
+}
+
+static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *opts)
+{
+ /*
+ * We have switched to a new branch; is it building on
+ * top of another branch, and if so does that other branch
+ * have changes we do not have yet?
+ */
+ char *base;
+ unsigned char sha1[20];
+ struct commit *ours, *theirs;
+ const char *msgfmt;
+ char symmetric[84];
+ int show_log;
+
+ if (!resolve_ref(new->path, sha1, 1, NULL))
+ return;
+ ours = lookup_commit(sha1);
+
+ if (!find_build_base(new->path, &base))
+ return;
+
+ sprintf(symmetric, "%s", sha1_to_hex(sha1));
+
+ /*
+ * Ok, it is tracking base; is it ahead of us?
+ */
+ if (!resolve_ref(base, sha1, 1, NULL))
+ return;
+ theirs = lookup_commit(sha1);
+
+ sprintf(symmetric + 40, "...%s", sha1_to_hex(sha1));
+
+ if (!hashcmp(sha1, ours->object.sha1))
+ return; /* we are the same */
+
+ show_log = 1;
+ if (in_merge_bases(theirs, &ours, 1)) {
+ msgfmt = "You are ahead of the tracked branch '%s'\n";
+ show_log = 0;
+ }
+ else if (in_merge_bases(ours, &theirs, 1))
+ msgfmt = "Your branch can be fast-forwarded to the tracked branch '%s'\n";
+ else
+ msgfmt = "Both your branch and the tracked branch '%s' have own changes, you would eventually need to merge\n";
+
+ if (!prefixcmp(base, "refs/remotes/"))
+ base += strlen("refs/remotes/");
+ fprintf(stderr, msgfmt, base);
+
+ if (show_log) {
+ const char *args[32];
+ int ac;
+
+ ac = 0;
+ args[ac++] = "log";
+ args[ac++] = "--pretty=oneline";
+ args[ac++] = "--abbrev-commit";
+ args[ac++] = "--left-right";
+ args[ac++] = "--boundary";
+ args[ac++] = symmetric;
+ args[ac++] = "--";
+ args[ac] = NULL;
+
+ run_command_v_opt(args, RUN_GIT_CMD);
+ }
+}
+
+
static void update_refs_for_switch(struct checkout_opts *opts,
struct branch_info *old,
struct branch_info *new)
@@ -332,6 +466,8 @@ static void update_refs_for_switch(struct checkout_opts *opts,
}
remove_branch_state();
strbuf_release(&msg);
+ if (new->path)
+ adjust_to_tracking(new, opts);
}
static int switch_branches(struct checkout_opts *opts,
next prev parent reply other threads:[~2008-02-17 1:09 UTC|newest]
Thread overview: 71+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-02-08 4:44 Minor annoyance with git push Martin Langhoff
2008-02-08 4:50 ` Martin Langhoff
2008-02-08 7:48 ` Junio C Hamano
2008-02-09 11:22 ` Steffen Prohaska
2008-02-10 3:44 ` Junio C Hamano
2008-02-10 12:21 ` Johannes Schindelin
2008-02-08 11:52 ` Johannes Schindelin
2008-02-08 22:23 ` Martin Langhoff
2008-02-08 22:27 ` Mike Hommey
2008-02-08 5:38 ` Sean
2008-02-08 6:29 ` Steffen Prohaska
2008-02-08 11:50 ` Johannes Schindelin
2008-02-08 22:27 ` Martin Langhoff
2008-02-08 22:57 ` Johannes Schindelin
2008-02-09 2:46 ` Jeff King
2008-02-09 2:54 ` Jeff King
2008-02-09 13:04 ` Johannes Schindelin
2008-02-09 13:22 ` Jeff King
2008-02-09 11:22 ` Steffen Prohaska
2008-02-09 3:00 ` Jeff King
2008-02-09 3:24 ` Junio C Hamano
2008-02-09 3:55 ` Jeff King
2008-02-09 11:50 ` Martin Langhoff
2008-02-09 13:06 ` Johannes Schindelin
2008-02-10 2:24 ` Junio C Hamano
2008-02-10 10:13 ` Jeff King
2008-02-10 12:22 ` Johannes Schindelin
2008-02-17 1:08 ` Junio C Hamano [this message]
2008-02-17 3:31 ` [RFC] checkout to notice forks (Re: Minor annoyance with git push) Daniel Barkalow
2008-02-17 4:11 ` Junio C Hamano
2008-02-17 6:39 ` Daniel Barkalow
2008-02-17 7:37 ` Junio C Hamano
2008-02-17 17:36 ` Daniel Barkalow
2008-02-17 12:28 ` Jeff King
2008-02-20 16:01 ` Santi Béjar
2008-02-19 17:03 ` Martin Langhoff
2008-02-20 23:05 ` [PATCH] checkout: tone down the "forked status" diagnostic messages Junio C Hamano
2008-02-21 1:45 ` Jeff King
2008-02-21 3:42 ` [PATCH] checkout: updates to tracking report Junio C Hamano
2008-02-21 5:27 ` Jay Soffian
2008-02-21 17:02 ` Daniel Barkalow
2008-02-21 2:56 ` [PATCH] checkout: tone down the "forked status" diagnostic messages Jay Soffian
2008-02-09 10:53 ` Minor annoyance with git push Steffen Prohaska
2008-02-09 13:10 ` Johannes Schindelin
2008-02-10 2:07 ` Junio C Hamano
2008-02-10 2:15 ` Johannes Schindelin
2008-02-10 10:17 ` Jeff King
2008-02-10 12:20 ` Johannes Schindelin
2008-02-10 12:23 ` Jeff King
2008-02-10 13:04 ` Johannes Schindelin
2008-02-10 13:07 ` Jeff King
2008-02-20 8:23 ` Junio C Hamano
2008-02-20 13:06 ` Johannes Schindelin
2008-02-20 15:20 ` Jay Soffian
2008-02-20 15:38 ` Johannes Schindelin
2008-02-21 22:35 ` Steven Walter
2008-02-22 0:11 ` Johannes Schindelin
2008-02-20 14:03 ` Jeff King
2008-02-20 17:54 ` Junio C Hamano
2008-02-20 18:15 ` Jeff King
2008-02-20 18:17 ` Jeff King
2008-02-20 18:19 ` Junio C Hamano
2008-02-20 18:23 ` Jeff King
2008-02-10 14:03 ` Wincent Colaiuta
2008-02-10 15:02 ` Steven Walter
2008-02-10 16:29 ` Johannes Schindelin
2008-02-10 16:26 ` Johannes Schindelin
2008-02-10 18:18 ` Wincent Colaiuta
2008-02-10 22:34 ` Jeff King
2008-02-10 22:59 ` Junio C Hamano
2008-02-10 23:29 ` Jeff King
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=7vfxvs75kp.fsf_-_@gitster.siamese.dyndns.org \
--to=gitster@pobox.com \
--cc=barkalow@iabervon.org \
--cc=git@vger.kernel.org \
--cc=johannes.schindelin@gmx.de \
--cc=martin.langhoff@gmail.com \
--cc=peff@peff.net \
--cc=prohaska@zib.de \
/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).