Subject: [PATCH 7/7] checkout: prevent checking out a branch being rebased in another worktree

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Sun, 17 Apr 2016 19:59:25 +0700

We failed to detect this case because the rebase-in-progress worktree
has HEAD in detached state. Some more poking around is needed to
determine if a rebase is in progress.

Note that even though bisect can also put a worktree in detached state
and hide the real branch, we allow to checkout anyway. This is because
unlike rebase, bisect does not update the branch. Yes it's still a bit
confusing when the user doing the bisecting realizes that the branch is
updated elsewhere, but at least we do not lose any valuable ref update.

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 worktree.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/worktree.c b/worktree.c
index 3b7c6f2..6dc40c2 100644
--- a/worktree.c
+++ b/worktree.c
@@ -2,6 +2,7 @@
 #include "refs.h"
 #include "strbuf.h"
 #include "worktree.h"
+#include "wt-status.h"
 
 void free_worktrees(struct worktree **worktrees)
 {
@@ -202,6 +203,28 @@ char *find_shared_symref(const char *symref, const char *target)
 	for (i = 0; worktrees[i]; i++) {
 		struct worktree *wt = worktrees[i];
 
+		if (wt->is_detached) {
+			struct wt_status_state wss;
+			int found;
+
+			memset(&wss, 0, sizeof(wss));
+			wss.wt = wt;
+			wt_status_get_state(&wss, 0);
+			found = (wss.rebase_in_progress ||
+				 wss.rebase_interactive_in_progress) &&
+				wss.branch &&
+				starts_with(target, "refs/heads/") &&
+				!strcmp(wss.branch,
+					target + strlen("refs/heads/"));
+			free(wss.branch);
+			free(wss.onto);
+			free(wss.detached_from);
+			if (found) {
+				existing = xstrdup(wt->path);
+				break;
+			}
+		}
+
 		strbuf_reset(&path);
 		strbuf_reset(&sb);
 		strbuf_addf(&path, "%s/%s",
-- 
2.8.0.rc0.210.gd302cd2