summaryrefslogtreecommitdiffstats
path: root/project.py
diff options
context:
space:
mode:
authorRemy Böhmer <oss@bohmer.net>2020-12-15 18:49:02 +0100
committerMike Frysinger <vapier@google.com>2020-12-26 07:30:40 +0000
commit1469c28ec3e221cf08a9f83a415945443eac0be4 (patch)
tree43308c66eae2beac5858ece2fe90dcfb5e5abb9e /project.py
parent8add62325dbe4df60cde1af6b093d99e79685140 (diff)
downloadgit-repo-1469c28ec3e221cf08a9f83a415945443eac0be4.tar.gz
project: detach HEAD in internal worktree checkout.
When checkout is done with Git worktrees then the HEAD in the bare-git repositories point to the initialized default (e.g. 'refs/heads/master'). This default branch does not exist locally and is not automatically created. When a user now creates a branch in any git repository named 'master' then it is no longer possible to get rid of this branch, neither is it possible to switch to another branch and switch back to this master branch. Git concludes the 'master' branch is already checked out (in the bare Git) and that results in a lockdown of this master branch. To repoduce this issue, run these commands in a repo tree checked out with --worktree: - git checkout master # assuming the remote repo has a master branch, # a local tracking branch master is created here - git checkout -b temp - git checkout master # This one now fails - git branch -d master # fails too The failure is caused by Git assuming the master branch is checked out by the bare git repository since HEAD is pointing towards it. To workaround this, we always detach HEAD in the bare-git when syncing. We don't need it to point to a ref in general, but we would like it to be valid so git tools "just work" if they're run in here. Signed-off-by: Remy Bohmer <oss@bohmer.net> Change-Id: I15c96604363c41f0d01c42f533174393097daeb5 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/290985 Reviewed-by: Mike Frysinger <vapier@google.com>
Diffstat (limited to 'project.py')
-rw-r--r--project.py9
1 files changed, 7 insertions, 2 deletions
diff --git a/project.py b/project.py
index cb78ff72..343452ad 100644
--- a/project.py
+++ b/project.py
@@ -2558,6 +2558,8 @@ class Project(object):
2558 2558
2559 base = R_WORKTREE_M 2559 base = R_WORKTREE_M
2560 active_git = self.work_git 2560 active_git = self.work_git
2561
2562 self._InitAnyMRef(HEAD, self.bare_git, detach=True)
2561 else: 2563 else:
2562 base = R_M 2564 base = R_M
2563 active_git = self.bare_git 2565 active_git = self.bare_git
@@ -2567,7 +2569,7 @@ class Project(object):
2567 def _InitMirrorHead(self): 2569 def _InitMirrorHead(self):
2568 self._InitAnyMRef(HEAD, self.bare_git) 2570 self._InitAnyMRef(HEAD, self.bare_git)
2569 2571
2570 def _InitAnyMRef(self, ref, active_git): 2572 def _InitAnyMRef(self, ref, active_git, detach=False):
2571 cur = self.bare_ref.symref(ref) 2573 cur = self.bare_ref.symref(ref)
2572 2574
2573 if self.revisionId: 2575 if self.revisionId:
@@ -2580,7 +2582,10 @@ class Project(object):
2580 dst = remote.ToLocal(self.revisionExpr) 2582 dst = remote.ToLocal(self.revisionExpr)
2581 if cur != dst: 2583 if cur != dst:
2582 msg = 'manifest set to %s' % self.revisionExpr 2584 msg = 'manifest set to %s' % self.revisionExpr
2583 active_git.symbolic_ref('-m', msg, ref, dst) 2585 if detach:
2586 active_git.UpdateRef(ref, dst, message=msg, detach=True)
2587 else:
2588 active_git.symbolic_ref('-m', msg, ref, dst)
2584 2589
2585 def _CheckDirReference(self, srcdir, destdir, share_refs): 2590 def _CheckDirReference(self, srcdir, destdir, share_refs):
2586 # Git worktrees don't use symlinks to share at all. 2591 # Git worktrees don't use symlinks to share at all.