All of lore.kernel.org
 help / color / mirror / Atom feed
From: Duy Nguyen <pclouds@gmail.com>
To: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Cc: frank kulow <kulow.f@googlemail.com>,
	Git Mailing List <git@vger.kernel.org>
Subject: Re: "git branch -f" corrupt other worktree
Date: Fri, 3 May 2019 00:16:13 +0700	[thread overview]
Message-ID: <20190502171612.GA13673@ash> (raw)
In-Reply-To: <CACsJy8A67x5wtbTe9Zk6URLZOqMNUFaLuNyZSVdYkZ1Z3y=6+A@mail.gmail.com>

On Thu, May 02, 2019 at 08:05:57PM +0700, Duy Nguyen wrote:
> The difficulty will be coming up with some sane UI that can
> handle that and not leave too many traps behind. I can't see that UI.

Well, I'm still thinking about it. And perhaps a good UI is not that
far away. The following hacky patch does three things:

1. it resolves "foo" to "refs/worktree/foo" if neither refs/heads/foo
   or refs/tags/foo exists.

2. it pretty prints refs/worktree/foo as worktree/foo

3. "git branch" has a new option --per-worktree that creates
   refs/worktree/foo instead of refs/heads/foo.

The idea here is we manage/decide per-worktree or shared refs at
branch/tag creation time. After that we use it like a normal
branch/tag. Point #1 helps the "normal" part.

Point #2 could even pretty print it to "foo" to make it even more
normal, but I feel that the distinction between per-worktree and
shared should still be more visible, hence "worktree/foo".

--per-worktree is pretty much a placeholder name. If we could find a
good name (and --worktre is already taken), then it could be added in
more places where a branch may be created.

It's far from complete. For example, refs/worktree/foo is not
considered a branch by any command, Only those inside refs/heads are
at the moment.

When I added refs/worktree/ namespace I didn't think that far ahead,
what kind of refs should be in there. But maybe we can still have
branches in refs/worktree/heads/ and tags in refs/worktree/tags/. Or
perhaps all refs/worktree/ should only contain branches, tags are
always shared (it's shared with remotes now even, at least in common
case)...

With more details worked out, perhaps we can make it work.

-- 8< --
diff --git a/branch.c b/branch.c
index 28b81a7e02..e5d738efa7 100644
--- a/branch.c
+++ b/branch.c
@@ -242,6 +242,8 @@ N_("\n"
 "will track its remote counterpart, you may want to use\n"
 "\"git push -u\" to set the upstream config as you push.");
 
+int create_branch_per_worktree;
+
 void create_branch(struct repository *r,
 		   const char *name, const char *start_name,
 		   int force, int clobber_head_ok, int reflog,
@@ -308,6 +310,9 @@ void create_branch(struct repository *r,
 	if (reflog)
 		log_all_ref_updates = LOG_REFS_NORMAL;
 
+	if (create_branch_per_worktree)
+		strbuf_splice(&ref, 0, 11, "refs/worktree/", 14);
+
 	if (!dont_change_ref) {
 		struct ref_transaction *transaction;
 		struct strbuf err = STRBUF_INIT;
diff --git a/builtin/branch.c b/builtin/branch.c
index d4359b33ac..8839c6f33f 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -605,6 +605,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	int icase = 0;
 	static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
 	struct ref_format format = REF_FORMAT_INIT;
+	int per_worktree = 0;
 
 	struct option options[] = {
 		OPT_GROUP(N_("Generic options")),
@@ -613,6 +614,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT__QUIET(&quiet, N_("suppress informational messages")),
 		OPT_SET_INT('t', "track",  &track, N_("set up tracking mode (see git-pull(1))"),
 			BRANCH_TRACK_EXPLICIT),
+		OPT_BOOL(0, "per-worktree",  &per_worktree, N_("create per-worktree branch")),
 		OPT_SET_INT_F(0, "set-upstream", &track, N_("do not use"),
 			BRANCH_TRACK_OVERRIDE, PARSE_OPT_HIDDEN),
 		OPT_STRING('u', "set-upstream-to", &new_upstream, N_("upstream"), N_("change the upstream info")),
@@ -829,12 +831,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		git_config_set_multivar(buf.buf, NULL, NULL, 1);
 		strbuf_release(&buf);
 	} else if (argc > 0 && argc <= 2) {
+		extern int create_branch_per_worktree;
+
 		if (filter.kind != FILTER_REFS_BRANCHES)
 			die(_("-a and -r options to 'git branch' do not make sense with a branch name"));
 
 		if (track == BRANCH_TRACK_OVERRIDE)
 			die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead."));
 
+		create_branch_per_worktree = per_worktree;
 		create_branch(the_repository,
 			      argv[0], (argc == 2) ? argv[1] : head,
 			      force, 0, reflog, quiet, track);
diff --git a/refs.c b/refs.c
index 142888a40a..8d01a80e07 100644
--- a/refs.c
+++ b/refs.c
@@ -479,7 +479,9 @@ const char *prettify_refname(const char *name)
 {
 	if (skip_prefix(name, "refs/heads/", &name) ||
 	    skip_prefix(name, "refs/tags/", &name) ||
-	    skip_prefix(name, "refs/remotes/", &name))
+	    skip_prefix(name, "refs/remotes/", &name) ||
+	    (starts_with(name, "refs/worktree/") &&
+	     skip_prefix(name, "refs/", &name)))
 		; /* nothing */
 	return name;
 }
@@ -491,6 +493,7 @@ static const char *ref_rev_parse_rules[] = {
 	"refs/heads/%.*s",
 	"refs/remotes/%.*s",
 	"refs/remotes/%.*s/HEAD",
+	"refs/worktree/%.*s",
 	NULL
 };
 
-- 8< --

      parent reply	other threads:[~2019-05-02 17:16 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-02 11:58 "git branch -f" corrupt other worktree frank kulow
2019-05-02 12:29 ` Duy Nguyen
2019-05-02 12:51   ` Ævar Arnfjörð Bjarmason
2019-05-02 13:05     ` Duy Nguyen
2019-05-02 13:49       ` Duy Nguyen
2019-05-02 17:16       ` Duy Nguyen [this message]

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=20190502171612.GA13673@ash \
    --to=pclouds@gmail.com \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=kulow.f@googlemail.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.