From: Junio C Hamano <gitster@pobox.com>
To: Thomas Rast <trast@student.ethz.ch>
Cc: git@vger.kernel.org
Subject: Re: [PATCH v2] checkout: implement "-" shortcut name for last branch
Date: Thu, 15 Jan 2009 12:11:31 -0800 [thread overview]
Message-ID: <7vocy8s51o.fsf@gitster.siamese.dyndns.org> (raw)
In-Reply-To: 1231978322-21228-1-git-send-email-trast@student.ethz.ch
Thomas Rast <trast@student.ethz.ch> writes:
> Let git-checkout save the old branch as a symref in LAST_HEAD, and
> make 'git checkout -' switch back to LAST_HEAD, like 'cd -' does in
> the shell.
I do not like this for two reasons.
I will not dispute that you would need to have "checkout" and other branch
switching operations to record where you were in order to be able to refer
to "where I was". And as Dscho and others point out, there already is an
existing mechanism that does exactly that, so it _might_ be easier to work
with an extra LAST_HEAD, it is not absolutely necessary.
I do not see a reason to limit the new notation "where I was" only to "git
checkout". Wouldn't it be handy if you can use the notation as the other
branch to merge from, or the commit to rebase on?
"cd -" is a very good analogy why your "-" shortcut is a short-sighted
convenience feature that is too narrow and not well designed. "cd -" can
go back, but you cannot say "ls -" to list the contents of the previous
directory.
So if this topic were "Introduce LAST_HEAD to always keep track of the
branch I was on before the current branch", and were advertised as "You
can use this throughout git to say things like 'git checkout LAST_HEAD',
'git merge LAST_HEAD', and 'git rebase LAST_HEAD'", I think it might have
made a bit more sense. You could _additionally_ say "because switching to
LAST_HEAD happens very often, there is another short cut 'checkout -' but
that is exactly the same as 'checkout LAST_HEAD'".
Another reason is the one level limitation. If we do not use LAST_HEAD,
and instead used HEAD reflog, to get to this information, there is no
reason we cannot to give an equally easy access to the second from the
last branch the user was on.
So I think it is just the matter of coming up with a clever syntax that
works on reflogs to name the nth last branch we were on and teach that
syntax to both get_sha1() and resolve_ref().
With the attached illustration patch,
$ git checkout junk
$ git chekcout master
$ git checkout @{-1}
will take you back to junk branch. It probably would serve as a starting
point, if anybody is interested.
NOTE!
* It will report "Switched to branch "junk", not "junk (@{-1})" or
anything that hints the user used this new syntax. switch_branches()
may need to be given more information to distinguish the name the end
user spelled to specify the branch (e.g. "@{-1}") and the actual name
of the branch (e.g. "junk"), and use the former together with the
latter when reporting to the end user and use the latter only to record
what happened to the reflog. But this is a very minor point.
* The reflog parser only parses "checkout" and not rebase action. It
also does not notice "git checkout HEAD^" is not switching to a real
branch.
* The code read the reflog twice, first to count how many branch
switching there are and then to locate the N-th entry we are interested
in, because I was lazy. We may want an API to enumerate reflog entries
in reverse.
* interpret_nth_last_branch() is not hooked to get_sha1() codepath in
this patch, so this is still only applicable to "git checkout". But it
should be trivial to do so.
builtin-checkout.c | 10 +++++-
cache.h | 1 +
sha1_name.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 87 insertions(+), 2 deletions(-)
diff --git c/builtin-checkout.c w/builtin-checkout.c
index b5dd9c0..a3b69d6 100644
--- c/builtin-checkout.c
+++ w/builtin-checkout.c
@@ -361,8 +361,14 @@ struct branch_info {
static void setup_branch_path(struct branch_info *branch)
{
struct strbuf buf = STRBUF_INIT;
- strbuf_addstr(&buf, "refs/heads/");
- strbuf_addstr(&buf, branch->name);
+
+ if (!interpret_nth_last_branch(branch->name, &buf)) {
+ branch->name = xstrdup(buf.buf);
+ strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
+ } else {
+ strbuf_addstr(&buf, "refs/heads/");
+ strbuf_addstr(&buf, branch->name);
+ }
branch->path = strbuf_detach(&buf, NULL);
}
diff --git c/cache.h w/cache.h
index 8e1af26..0dd9168 100644
--- c/cache.h
+++ w/cache.h
@@ -663,6 +663,7 @@ extern int read_ref(const char *filename, unsigned char *sha1);
extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *);
extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
+extern int interpret_nth_last_branch(const char *str, struct strbuf *);
extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules);
extern const char *ref_rev_parse_rules[];
diff --git c/sha1_name.c w/sha1_name.c
index 159c2ab..6377264 100644
--- c/sha1_name.c
+++ w/sha1_name.c
@@ -674,6 +674,84 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1)
return retval;
}
+struct grab_nth_branch_switch_cbdata {
+ int counting;
+ int nth;
+ struct strbuf *buf;
+};
+
+static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
+ const char *email, unsigned long timestamp, int tz,
+ const char *message, void *cb_data)
+{
+ struct grab_nth_branch_switch_cbdata *cb = cb_data;
+ const char *match = NULL;
+
+ if (!prefixcmp(message, "checkout: moving to "))
+ match = message + strlen("checkout: moving to ");
+ else if (!prefixcmp(message, "checkout: moving from ")) {
+ const char *cp = message + strlen("checkout: moving from ");
+ if ((cp = strstr(cp, " to ")) != NULL) {
+ match = cp + 4;
+ }
+ }
+
+ if (!match)
+ return 0;
+
+ if (cb->counting) {
+ cb->nth++;
+ return 0;
+ }
+
+ if (--cb->nth <= 0) {
+ size_t len = strlen(match);
+ while (match[len-1] == '\n')
+ len--;
+ strbuf_reset(cb->buf);
+ strbuf_add(cb->buf, match, len);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * This reads "@{-N}" syntax, finds the name of the Nth previous
+ * branch we were on, and places the name of the branch in the given
+ * buf and returns 0 if successful.
+ *
+ * If the input is not of the accepted format, it returns a negative
+ * number to signal an error.
+ */
+int interpret_nth_last_branch(const char *name, struct strbuf *buf)
+{
+ int nth, i;
+ struct grab_nth_branch_switch_cbdata cb;
+
+ if (name[0] != '@' || name[1] != '{' || name[2] != '-')
+ return -1;
+ for (i = 3, nth = 0; name[i] && name[i] != '}'; i++) {
+ char ch = name[i];
+ if ('0' <= ch && ch <= '9')
+ nth = nth * 10 + ch - '0';
+ else
+ return -1;
+ }
+ if (nth < 0 || 10 <= nth)
+ return -1;
+
+ cb.counting = 1;
+ cb.nth = 0;
+ cb.buf = buf;
+ for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
+
+ cb.counting = 0;
+ cb.nth -= nth;
+ cb.buf = buf;
+ for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
+ return 0;
+}
+
/*
* This is like "get_sha1_basic()", except it allows "sha1 expressions",
* notably "xyz^" for "parent of xyz"
next prev parent reply other threads:[~2009-01-15 20:13 UTC|newest]
Thread overview: 102+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-15 0:06 [PATCH] checkout: implement "-" shortcut name for last branch Thomas Rast
2009-01-15 0:12 ` [PATCH v2] " Thomas Rast
2009-01-15 7:27 ` Johannes Sixt
2009-01-15 13:15 ` Johannes Schindelin
2009-01-15 13:59 ` Thomas Rast
2009-01-15 14:09 ` Johannes Schindelin
2009-01-15 14:17 ` Johannes Schindelin
2009-01-15 20:12 ` Junio C Hamano
2009-01-15 20:35 ` Johannes Schindelin
2009-01-16 12:52 ` [PATCH] revision walker: include a detached HEAD in --all Johannes Schindelin
2009-01-16 13:12 ` Santi Béjar
2009-01-16 13:17 ` Johannes Schindelin
2009-01-16 13:22 ` David Kastrup
2009-01-16 13:46 ` Santi Béjar
2009-01-16 13:50 ` Santi Béjar
2009-01-18 6:01 ` Junio C Hamano
2009-01-18 6:36 ` Junio C Hamano
2009-01-18 14:06 ` Johannes Schindelin
2009-01-18 13:42 ` Johannes Schindelin
2009-01-15 16:32 ` [PATCH v2] checkout: implement "-" shortcut name for last branch Johan Herland
2009-01-15 16:50 ` Johannes Schindelin
2009-01-15 20:11 ` Junio C Hamano [this message]
2009-01-15 20:50 ` Junio C Hamano
2009-01-17 3:30 ` [PATCH/RFC v3 0/6] N-th last checked out branch Thomas Rast
2009-01-17 5:52 ` Johannes Schindelin
2009-01-17 13:38 ` Thomas Rast
2009-01-17 13:40 ` [PATCH/RFC v3bis 1/2] sha1_name: implement @{-N} syntax for N-th last checked out Thomas Rast
2009-01-17 13:40 ` [PATCH/RFC v3bis 2/2] checkout: implement '@{-N}' and '-' special abbreviations Thomas Rast
2009-01-17 15:04 ` [PATCH] interpret_nth_last_branch(): avoid traversing the reflogs twice Johannes Schindelin
2009-01-17 16:09 ` [PATCH/RFC v4 0/5] N-th last checked out branch Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 1/5] checkout: implement "@{-N}" shortcut name for N-th last branch Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 2/5] sha1_name: tweak @{-N} lookup Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 3/5] sha1_name: support @{-N} syntax in get_sha1() Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 4/5] checkout: implement "-" abbreviation, add docs and tests Thomas Rast
2009-01-17 16:09 ` [PATCH/RFC v4 5/5] interpret_nth_last_branch(): avoid traversing the reflogs twice Thomas Rast
2009-01-17 18:08 ` [PATCH 6/5] Fix parsing of @{-1}@{1} Johannes Schindelin
2009-01-17 20:02 ` Junio C Hamano
2009-01-17 21:22 ` Johannes Schindelin
2009-01-17 19:57 ` [PATCH/RFC v4 4/5] checkout: implement "-" abbreviation, add docs and tests Junio C Hamano
2009-01-17 17:55 ` [PATCH/RFC v4 3/5] sha1_name: support @{-N} syntax in get_sha1() Johannes Schindelin
2009-01-17 19:37 ` Junio C Hamano
2009-01-18 0:54 ` [PATCH/RFC v4 2/5] sha1_name: tweak @{-N} lookup Junio C Hamano
2009-01-17 16:49 ` [PATCH/RFC v4 0/5] N-th last checked out branch Johannes Schindelin
2009-01-17 19:13 ` [PATCH] interpret_nth_last_branch(): avoid traversing the reflogs twice Junio C Hamano
2009-01-17 19:29 ` Johannes Schindelin
2009-01-18 0:43 ` Junio C Hamano
2009-01-18 1:12 ` Johannes Schindelin
2009-01-18 7:25 ` Junio C Hamano
2009-01-18 20:59 ` Johannes Schindelin
2009-01-19 8:08 ` Junio C Hamano
2009-01-19 8:19 ` Junio C Hamano
2009-01-19 12:33 ` Johannes Schindelin
2009-01-20 0:11 ` Thomas Rast
2009-01-20 0:23 ` Johannes Schindelin
2009-01-20 0:41 ` Thomas Rast
2009-01-20 6:21 ` [PATCH] interpret_nth_last_branch(): plug small memleak Junio C Hamano
2009-01-20 10:15 ` Johannes Schindelin
2009-01-20 6:22 ` [PATCH] Introduce for_each_recent_reflog_ent() Junio C Hamano
2009-01-20 10:15 ` Johannes Schindelin
2009-01-20 8:35 ` [PATCH] interpret_nth_last_branch(): avoid traversing the reflogs twice Junio C Hamano
2009-01-21 0:16 ` [VALGRIND PATCH for nth_last patch series] Fix invalid memory access Johannes Schindelin
2009-01-21 8:45 ` Junio C Hamano
2009-01-21 9:18 ` Thomas Rast
2009-01-21 10:13 ` Junio C Hamano
2009-01-21 12:06 ` Johannes Schindelin
2009-01-24 22:21 ` Thomas Rast
2009-01-24 22:23 ` [PATCH next] t1505: remove debugging cruft Thomas Rast
2009-01-25 20:35 ` Junio C Hamano
2009-01-21 11:56 ` [VALGRIND PATCH for nth_last patch series] Fix invalid memory access Johannes Schindelin
2009-01-19 12:41 ` [PATCH] @{-<n>}: avoid crash with corrupt reflog Johannes Schindelin
2009-01-19 14:57 ` Johannes Schindelin
2009-01-17 3:30 ` [PATCH/RFC v3 1/6] reflog: refactor parsing and checking Thomas Rast
2009-01-17 5:35 ` Johannes Schindelin
2009-01-17 3:30 ` [PATCH/RFC v3 2/6] reflog: refactor log open+mmap Thomas Rast
2009-01-17 5:40 ` Johannes Schindelin
2009-01-17 3:30 ` [PATCH/RFC v3 3/6] reflog: make for_each_reflog_ent use mmap Thomas Rast
2009-01-17 3:30 ` [PATCH/RFC v3 4/6] reflog: add backwards iterator Thomas Rast
2009-01-17 3:30 ` [PATCH/RFC v3 5/6] sha1_name: implement @{-N} syntax for N-th last checked out Thomas Rast
2009-01-17 3:30 ` [PATCH/RFC v3 6/6] checkout: implement '@{-N}' and '-' special abbreviations Thomas Rast
2009-01-16 12:31 ` [PATCH v2] checkout: implement "-" shortcut name for last branch Johannes Schindelin
2009-01-15 0:45 ` [PATCH] " Johannes Schindelin
2009-01-15 14:01 ` Thomas Rast
2009-01-15 14:14 ` Johannes Schindelin
2009-01-15 17:05 ` Thomas Rast
2009-01-15 18:34 ` Johannes Schindelin
2009-01-16 9:08 ` Thomas Rast
2009-01-16 11:18 ` Johannes Schindelin
2009-01-18 1:38 ` [TOY PATCH] git-resurrect: find traces of a branch name and resurrect it Thomas Rast
2009-01-18 16:19 ` Johannes Schindelin
2009-01-20 9:01 ` Thomas Rast
2009-01-20 16:57 ` Boyd Stephen Smith Jr.
2009-01-20 20:50 ` Boyd Stephen Smith Jr.
2009-01-23 20:03 ` [PATCH] contrib " Thomas Rast
2009-01-23 21:00 ` Boyd Stephen Smith Jr.
2009-01-26 11:54 ` Thomas Rast
2009-01-26 12:40 ` [PATCH v2] " Thomas Rast
2009-01-27 6:31 ` Junio C Hamano
2009-01-30 22:52 ` Thomas Rast
2009-02-01 21:34 ` [PATCH v3] " Thomas Rast
2009-02-02 2:31 ` Junio C Hamano
2009-02-04 10:04 ` [PATCH v4] " Thomas Rast
2009-02-05 8:38 ` Junio C Hamano
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=7vocy8s51o.fsf@gitster.siamese.dyndns.org \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
--cc=trast@student.ethz.ch \
/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).