git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 10/16] worktree: make branch creation distinct from worktree population

From
Eric Sunshine <sunshine@sunshineco.com>
Date
Jul 12, 2015, 19:20 UTC
Message-ID
<20150712192016.GA4410@flurp.local>
In-Reply-To
<CACsJy8BTTdWrCZNz=y686pgju5X8-2mPrNNQ-+z4ByeKD6O5Uw@mail.gmail.com>
On Sun, Jul 12, 2015 at 04:54:02PM +0700, Duy Nguyen wrote:
Show 25 quoted lines
> On Sun, Jul 12, 2015 at 10:27 AM, Eric Sunshine <sunshine@sunshineco.com> wrot> > In this case, it's easy enough to side-step the issue since there's no
> > need to call ref_exists() if the new branch was created successfully
> > (since we know it exists). The logic would effectively become this:
> >
> >     branch = ...
> >     if (create_new_branch) {
> >         exec "git branch newbranch branch"
> >         exec "git symbolic-ref HEAD newbranch"
> >     } else if (ref_exists(branch) && !detach)
> >         exec "git symbolic-ref HEAD branch"
> >     else
> >         exec "git update-ref HEAD $(git rev-parse branch)"
> >     exec "git reset --hard"
> 
> Yeah.. Another option we can take is deal with this at run-command.c
> level (and outside this series) because this could affect everywhere:
> by default, invalidate all cache after running any git commands. The
> caller can pass options to keep some cache intact if they know the
> command won't touch it.
> 
> If ref_exists() is the only thing we use, right now it does not use
> cache so we should be safe. If the new ref backend introduces a cache,
> they would need to examine all callers anyway, including this one. The
> cache in refs.c seems to be for for_each_ref.. only, which we don't
> call here.

In case I don't need to re-roll the series for some other reason, here's a squash-in making the above adjustment to patch 12/16, which Junio can pick up if he wants to:

---- 8< ----
From: Eric Sunshine <sunshine@sunshineco.com>
Subject: [PATCH] fixup! worktree: detect branch symref/detach and error conditions locally
Current logic is effectively:
    branch = ...
    if (create_new_branch) {
        run "git branch newbranch branch"
        branch = newbranch
    }
    if (!detach && ref_exists(branch)) {
        if (!force)
            die_if_already_checked_out(branch)
        run "git symbolic-ref HEAD branch"
    } else
        run "git update-ref HEAD $(git rev-parse branch)"
    run "git reset --hard"

The ref_exists() call following 'run "git branch newbranch branch"' works fine since ref_exists() hits the filesystem directly to answer the question rather than relying upon potentially stale cached information. However, this is potentially fragile if someone some day implements caching. Moreover, with pluggable backends on the horizon, we may not be able to rely upon ref_exists() in this process accurately reflecting changes made by a subprocess.

If new branch creation was successful, then we know it's a branch, and don't need to ask ref_exists() about it, thus we don't need to worry about ref_exists() possibly returning an answer based upon stale information, nor do we have to check if the new branch is already checked out elsewhere. Therefore, rework the logic slightly to become effectively:

    branch = ...
    if (create_new_branch) {
        run "git branch newbranch branch"
        run "git symbolic-ref HEAD newbranch"
    } else if (!detach && ref_exists(branch)) {
        if (!force)
            die_if_already_checked_out(branch)
        run "git symbolic-ref HEAD branch"
    } else
        run "git update-ref HEAD $(git rev-parse branch)"
    run "git reset --hard"
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
---
 builtin/worktree.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 51c57bc..39f87a4 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -195,8 +195,10 @@ static int add_worktree(const char *path, const char *refname,
 	if (file_exists(path) && !is_empty_dir(path))
 		die(_("'%s' already exists"), path);
 
-	if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
-	    ref_exists(symref.buf)) {
+	if (opts->force_new_branch)
+		;
+	else if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
+		 ref_exists(symref.buf)) {
 		if (!opts->force)
 			die_if_checked_out(symref.buf);
 	} else {
-- 
2.5.0.rc1.387.g8463c8d
Previous: Duy Nguyen
Message 31 of 31 in “worktree: use "git reset --hard" to populate worktree”
  1. 00/16 worktree: use "git reset --hard" to populate worktreeEric Sunshine, Jul 11, 2015
  2. 01/16 checkout: avoid resolving HEAD unnecessarilyEric Sunshine, Jul 11, 2015
  3. 02/16 checkout: name check_linked_checkouts() more meaningfullyEric Sunshine, Jul 11, 2015
  4. 03/16 checkout: improve die_if_checked_out() robustnessEric Sunshine, Jul 11, 2015
  5. 04/16 checkout: die_if_checked_out: simplify strbuf managementEric Sunshine, Jul 11, 2015
  6. 05/16 checkout: generalize die_if_checked_out() branch name argumentEric Sunshine, Jul 11, 2015
  7. 06/16 branch: publish die_if_checked_out()Eric Sunshine, Jul 11, 2015
  8. 07/16 worktree: simplify new branch (-b/-B) option checkingEric Sunshine, Jul 11, 2015
  9. 08/16 worktree: introduce options containerEric Sunshine, Jul 11, 2015
  10. 09/16 worktree: make --detach mutually exclusive with -b/-BEric Sunshine, Jul 11, 2015
  11. 10/16 worktree: make branch creation distinct from worktree populationEric Sunshine, Jul 11, 2015
  12. Duy NguyenJul 12, 2015
  13. Eric SunshineJul 12, 2015
  14. Duy NguyenJul 12, 2015
  15. Eric SunshineJul 12, 2015
  16. Eric SunshineJul 12, 2015
  17. Eric SunshineJul 12, 2015
  18. Duy NguyenJul 12, 2015
  19. 11/16 worktree: add_worktree: construct worktree-population command locallyEric Sunshine, Jul 11, 2015
  20. 12/16 worktree: detect branch symref/detach and error conditions locallyEric Sunshine, Jul 11, 2015
  21. 13/16 worktree: make setup of new HEAD distinct from worktree populationEric Sunshine, Jul 11, 2015
  22. 14/16 worktree: avoid resolving HEAD unnecessarilyEric Sunshine, Jul 11, 2015
  23. 15/16 worktree: populate via "git reset --hard" rather than "git checkout"Eric Sunshine, Jul 11, 2015
  24. 16/16 checkout: drop intimate knowledge of new worktree initial populationEric Sunshine, Jul 11, 2015
  25. Junio C HamanoJul 13, 2015
  26. Michael J GruberJul 14, 2015
  27. Duy NguyenJul 14, 2015
  28. Eric SunshineJul 14, 2015
  29. Eric SunshineJul 15, 2015
  30. Duy NguyenJul 15, 2015
  31. Eric SunshineJul 12, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.