Clarify detached HEAD access and attach writable test fixtures (#2230) · gitpython-developers/GitPython@6bcb25b · GitHub
Skip to content

Commit 6bcb25b

Browse files
Byroncodex
andcommitted
Clarify detached HEAD access and attach writable test fixtures (#2230)
<!-- agent --> Reading head.reference or active_branch raises TypeError when HEAD points directly to a commit, but the public documentation did not clearly explain how to access that commit. Document head.commit.hexsha for attached and detached HEADs, explain the reference setter/getter asymmetry, and clarify that active_branch requires an attached HEAD. Preserve the exception type and existing message prefix while adding a hint to use .commit or .object. Writable test fixtures assumed cloning produced an attached HEAD, so their branch access could fail when the source checkout was detached. Have with_rw_repo create and attach master at the requested revision when its clone is detached, retaining the clone's branch and tracking configuration otherwise. Explicitly attach the temporary bare remote to its own master branch before cloning it for remote tests. Assisted-by: GPT 6.0 Co-authored-by: GPT 6.0 <codex@openai.com>
1 parent b62e91b commit 6bcb25b

4 files changed

Lines changed: 52 additions & 10 deletions

File tree

doc/source/tutorial.rst

Lines changed: 7 additions & 1 deletion

git/refs/symbolic.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,14 @@ def _git_dir(repo: "Repo", path: Union[PathLike, None]) -> PathLike:
5959

6060

6161
class SymbolicReference:
62-
"""Special case of a reference that is symbolic.
62+
"""A reference that can point to another reference or be detached.
6363
64-
This does not point to a specific commit, but to another
65-
:class:`~git.refs.head.Head`, which itself specifies a commit.
64+
An attached :class:`~git.refs.head.HEAD` usually points to a
65+
:class:`~git.refs.head.Head`, which itself specifies a commit. A detached
66+
:class:`~git.refs.head.HEAD` points directly to a commit instead.
6667
67-
A typical example for a symbolic reference is :class:`~git.refs.head.HEAD`.
68+
Use :attr:`commit` to access the commit in either case, and :attr:`reference`
69+
to access the target reference when attached.
6870
"""
6971

7072
__slots__ = ("repo", "path")
@@ -416,7 +418,15 @@ def set_object(
416418

417419
@property
418420
def commit(self) -> "Commit":
419-
"""Query or set commits directly"""
421+
"""The commit this reference resolves to, whether detached or symbolic.
422+
423+
For example, ``repo.head.commit.hexsha`` returns the current commit ID
424+
both on a branch and with a detached HEAD. HEAD must resolve to an
425+
existing commit; an unborn branch in an empty repository has none.
426+
427+
Assigning updates the commit without changing whether this reference
428+
is detached.
429+
"""
420430
return self._get_commit()
421431

422432
@commit.setter
@@ -443,7 +453,10 @@ def _get_reference(self) -> "Reference":
443453
"""
444454
sha, target_ref_path = self._get_ref_info(self.repo, self.path)
445455
if target_ref_path is None:
446-
raise TypeError("%s is a detached symbolic reference as it points to %r" % (self, sha))
456+
raise TypeError(
457+
"%s is a detached symbolic reference as it points to %r. "
458+
"Use .commit or .object to access the target directly." % (self, sha)
459+
)
447460
return cast("Reference", self.from_path(self.repo, target_ref_path))
448461

449462
def set_reference(
@@ -531,6 +544,18 @@ def set_reference(
531544
# Aliased reference
532545
@property
533546
def reference(self) -> "Reference":
547+
"""The reference we point to, available only when not detached.
548+
549+
Check :attr:`is_detached` before reading this property if a target
550+
reference is required. To access the target commit or object in either
551+
state, use :attr:`commit` or :attr:`object` instead.
552+
553+
Assigning a reference keeps this reference symbolic. Assigning a git
554+
object or revision string detaches it; reading this property then raises.
555+
556+
:raise TypeError:
557+
If this reference is detached when reading the property.
558+
"""
534559
return self._get_reference()
535560

536561
@reference.setter

git/repo/base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,11 @@ def ignored(self, *paths: PathLike) -> List[str]:
11501150

11511151
@property
11521152
def active_branch(self) -> Head:
1153-
"""The name of the currently active branch.
1153+
"""The currently active branch.
1154+
1155+
Check ``repo.head.is_detached`` before accessing this property if HEAD
1156+
may be detached. To access the current commit in either state, use
1157+
``repo.head.commit`` instead.
11541158
11551159
:raise TypeError:
11561160
If HEAD is detached.

test/lib/helper.py

Lines changed: 9 additions & 2 deletions

0 commit comments

Comments
 (0)