0
# Git Objects
1
2
Core Git object types including commits, trees, blobs, and tags. These represent the fundamental data structures in Git repositories and provide object-oriented access to Git's content-addressable storage system.
3
4
## Capabilities
5
6
### Base Object Interface
7
8
All Git objects inherit from the base Object class providing common properties and methods.
9
10
```python { .api }
11
class Object:
12
@property
13
def oid(self) -> Oid:
14
"""Object identifier (SHA-1 hash)"""
15
16
@property
17
def type(self) -> int:
18
"""Object type (GIT_OBJECT_COMMIT, GIT_OBJECT_TREE, etc.)"""
19
20
@property
21
def size(self) -> int:
22
"""Object size in bytes"""
23
24
def peel(self, target_type: int) -> Object:
25
"""Peel object to target type"""
26
27
def __str__(self) -> str:
28
"""String representation of object"""
29
30
def __eq__(self, other) -> bool:
31
"""Compare objects by OID"""
32
33
# Object Type Constants
34
GIT_OBJECT_ANY: int
35
GIT_OBJECT_COMMIT: int
36
GIT_OBJECT_TREE: int
37
GIT_OBJECT_BLOB: int
38
GIT_OBJECT_TAG: int
39
GIT_OBJECT_INVALID: int
40
```
41
42
### Commit Objects
43
44
Commit objects represent snapshots in repository history with metadata about changes.
45
46
```python { .api }
47
class Commit(Object):
48
@property
49
def message(self) -> str:
50
"""Commit message"""
51
52
@property
53
def author(self) -> Signature:
54
"""Commit author signature"""
55
56
@property
57
def committer(self) -> Signature:
58
"""Commit committer signature"""
59
60
@property
61
def commit_time(self) -> int:
62
"""Commit timestamp"""
63
64
@property
65
def commit_time_offset(self) -> int:
66
"""Commit timezone offset"""
67
68
@property
69
def author_time(self) -> int:
70
"""Author timestamp"""
71
72
@property
73
def author_time_offset(self) -> int:
74
"""Author timezone offset"""
75
76
@property
77
def tree(self) -> Tree:
78
"""Root tree object"""
79
80
@property
81
def tree_id(self) -> Oid:
82
"""Root tree OID"""
83
84
@property
85
def parents(self) -> list[Commit]:
86
"""Parent commit objects"""
87
88
@property
89
def parent_ids(self) -> list[Oid]:
90
"""Parent commit OIDs"""
91
92
@property
93
def raw_message(self) -> bytes:
94
"""Raw commit message bytes"""
95
96
def message_trailers(self) -> dict[str, str]:
97
"""Parse commit message trailers"""
98
```
99
100
### Tree Objects
101
102
Tree objects represent directory structures in Git, containing references to blobs and other trees.
103
104
```python { .api }
105
class Tree(Object):
106
def __len__(self) -> int:
107
"""Number of entries in tree"""
108
109
def __getitem__(self, key: str | int) -> Object:
110
"""Get tree entry by name or index"""
111
112
def __contains__(self, name: str) -> bool:
113
"""Check if entry exists in tree"""
114
115
def __iter__(self):
116
"""Iterate over tree entries"""
117
118
@property
119
def id(self) -> Oid:
120
"""Tree object ID"""
121
122
def diff_to_tree(self, tree: 'Tree' = None, **kwargs) -> Diff:
123
"""Compare with another tree"""
124
125
def diff_to_workdir(self, **kwargs) -> Diff:
126
"""Compare with working directory"""
127
128
def diff_to_index(self, **kwargs) -> Diff:
129
"""Compare with index"""
130
131
class TreeEntry:
132
@property
133
def name(self) -> str:
134
"""Entry name"""
135
136
@property
137
def oid(self) -> Oid:
138
"""Entry object ID"""
139
140
@property
141
def filemode(self) -> int:
142
"""Entry file mode"""
143
144
@property
145
def type(self) -> int:
146
"""Entry object type"""
147
```
148
149
### Tree Builder
150
151
TreeBuilder enables programmatic construction of tree objects.
152
153
```python { .api }
154
class TreeBuilder:
155
def __init__(self, repo: Repository, tree: Tree = None):
156
"""Create tree builder, optionally from existing tree"""
157
158
def insert(self, name: str, oid: Oid, filemode: int):
159
"""Insert entry into tree"""
160
161
def remove(self, name: str):
162
"""Remove entry from tree"""
163
164
def __len__(self) -> int:
165
"""Number of entries"""
166
167
def __getitem__(self, name: str) -> Object:
168
"""Get entry by name"""
169
170
def __contains__(self, name: str) -> bool:
171
"""Check if entry exists"""
172
173
def write(self) -> Oid:
174
"""Write tree to object database"""
175
176
def clear(self):
177
"""Remove all entries"""
178
179
# File Mode Constants
180
GIT_FILEMODE_UNREADABLE: int
181
GIT_FILEMODE_TREE: int
182
GIT_FILEMODE_BLOB: int
183
GIT_FILEMODE_BLOB_EXECUTABLE: int
184
GIT_FILEMODE_LINK: int
185
GIT_FILEMODE_COMMIT: int
186
```
187
188
### Blob Objects
189
190
Blob objects store file content data in Git's object database.
191
192
```python { .api }
193
class Blob(Object):
194
@property
195
def data(self) -> bytes:
196
"""Blob content as bytes"""
197
198
@property
199
def size(self) -> int:
200
"""Blob size in bytes"""
201
202
@property
203
def is_binary(self) -> bool:
204
"""True if blob contains binary data"""
205
206
def diff(self, blob: 'Blob' = None, **kwargs) -> Patch:
207
"""Compare with another blob"""
208
209
class BlobIO:
210
"""Stream interface for large blob content"""
211
212
def __init__(self, blob: Blob):
213
"""Create stream from blob"""
214
215
def read(self, size: int = -1) -> bytes:
216
"""Read blob data"""
217
218
def readline(self, size: int = -1) -> bytes:
219
"""Read single line"""
220
221
def readlines(self, hint: int = -1) -> list[bytes]:
222
"""Read all lines"""
223
224
def __iter__(self):
225
"""Iterate over lines"""
226
```
227
228
### Tag Objects
229
230
Tag objects create named references to other Git objects with optional metadata.
231
232
```python { .api }
233
class Tag(Object):
234
@property
235
def name(self) -> str:
236
"""Tag name"""
237
238
@property
239
def target(self) -> Object:
240
"""Tagged object"""
241
242
@property
243
def target_id(self) -> Oid:
244
"""Tagged object ID"""
245
246
@property
247
def tagger(self) -> Signature:
248
"""Tag creator signature"""
249
250
@property
251
def message(self) -> str:
252
"""Tag message"""
253
254
@property
255
def raw_message(self) -> bytes:
256
"""Raw tag message bytes"""
257
258
def peel(self, target_type: int = None) -> Object:
259
"""Peel tag to target object type"""
260
```
261
262
### Object Identifiers
263
264
Oid class represents Git object identifiers (SHA-1 hashes).
265
266
```python { .api }
267
class Oid:
268
def __init__(self, raw: bytes | str):
269
"""Create OID from raw bytes or hex string"""
270
271
@property
272
def raw(self) -> bytes:
273
"""Raw bytes representation"""
274
275
@property
276
def hex(self) -> str:
277
"""Hexadecimal string representation"""
278
279
def __str__(self) -> str:
280
"""Hex string representation"""
281
282
def __eq__(self, other) -> bool:
283
"""Compare OIDs"""
284
285
def __hash__(self) -> int:
286
"""Hash for use in collections"""
287
288
# OID Constants
289
GIT_OID_RAWSZ: int # Raw OID size (20 bytes)
290
GIT_OID_HEXSZ: int # Hex OID size (40 chars)
291
GIT_OID_MINPREFIXLEN: int # Minimum prefix length
292
GIT_OID_HEX_ZERO: str # Zero OID hex string
293
```
294
295
### Signatures
296
297
Signature class represents author and committer information in commits and tags.
298
299
```python { .api }
300
class Signature:
301
def __init__(
302
self,
303
name: str,
304
email: str,
305
time: int = None,
306
offset: int = None,
307
encoding: str = 'utf-8'
308
):
309
"""
310
Create signature.
311
312
Parameters:
313
- name: Person's name
314
- email: Email address
315
- time: Unix timestamp (default: current time)
316
- offset: Timezone offset in minutes
317
- encoding: Text encoding
318
"""
319
320
@property
321
def name(self) -> str:
322
"""Person's name"""
323
324
@property
325
def email(self) -> str:
326
"""Email address"""
327
328
@property
329
def time(self) -> int:
330
"""Unix timestamp"""
331
332
@property
333
def offset(self) -> int:
334
"""Timezone offset in minutes"""
335
336
@property
337
def encoding(self) -> str:
338
"""Text encoding"""
339
340
def __str__(self) -> str:
341
"""String representation"""
342
343
def __eq__(self, other) -> bool:
344
"""Compare signatures"""
345
```
346
347
### Usage Examples
348
349
#### Working with Commits
350
351
```python
352
import pygit2
353
354
repo = pygit2.Repository('/path/to/repo')
355
356
# Get latest commit
357
commit = repo[repo.head.target]
358
print(f"Commit: {commit.oid}")
359
print(f"Author: {commit.author.name} <{commit.author.email}>")
360
print(f"Message: {commit.message}")
361
print(f"Tree: {commit.tree_id}")
362
363
# Walk commit history
364
for commit in repo.walk(repo.head.target):
365
print(f"{commit.oid}: {commit.message.split('\n')[0]}")
366
if len(commit.parents) > 1:
367
print(" (merge commit)")
368
```
369
370
#### Working with Trees and Blobs
371
372
```python
373
# Explore tree structure
374
tree = repo[commit.tree]
375
for entry in tree:
376
obj = repo[entry.oid]
377
if entry.type == pygit2.GIT_OBJECT_TREE:
378
print(f"Directory: {entry.name}/")
379
elif entry.type == pygit2.GIT_OBJECT_BLOB:
380
blob = obj
381
print(f"File: {entry.name} ({blob.size} bytes)")
382
if not blob.is_binary:
383
content = blob.data.decode('utf-8')
384
print(f" Preview: {content[:50]}...")
385
386
# Create new tree
387
builder = pygit2.TreeBuilder(repo)
388
blob_oid = repo.create_blob(b"Hello, World!")
389
builder.insert("hello.txt", blob_oid, pygit2.GIT_FILEMODE_BLOB)
390
tree_oid = builder.write()
391
```
392
393
#### Creating Objects
394
395
```python
396
# Create signature
397
signature = pygit2.Signature(
398
'John Doe',
399
'john@example.com'
400
)
401
402
# Create blob from data
403
blob_oid = repo.create_blob(b"File content")
404
405
# Create tree with blob
406
builder = pygit2.TreeBuilder(repo)
407
builder.insert("file.txt", blob_oid, pygit2.GIT_FILEMODE_BLOB)
408
tree_oid = builder.write()
409
410
# Create commit
411
commit_oid = repo.create_commit(
412
'refs/heads/main',
413
signature, # author
414
signature, # committer
415
'Add new file',
416
tree_oid,
417
[] # parents
418
)
419
420
# Create tag
421
tag_oid = repo.create_tag(
422
'v1.0.0',
423
commit_oid,
424
signature,
425
'Version 1.0.0 release'
426
)
427
```
428
429
#### Streaming Large Blobs
430
431
```python
432
# Stream large blob content
433
blob = repo[blob_oid]
434
if blob.size > 1024 * 1024: # > 1MB
435
stream = pygit2.BlobIO(blob)
436
while True:
437
chunk = stream.read(8192)
438
if not chunk:
439
break
440
# Process chunk
441
process_data(chunk)
442
```