git.vger.kernel.org archive mirror
 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 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).