0
# Repository Management
1
2
Git repository operations, branch management, commit handling, file operations, and version control workflows. Comprehensive coverage of repository-level operations including files, branches, tags, commits, and repository configuration.
3
4
## Capabilities
5
6
### Repository File Operations
7
8
```python { .api }
9
class ProjectFile(SaveMixin, ObjectDeleteMixin, RESTObject):
10
"""
11
Repository file object with content management.
12
13
Key Attributes:
14
- file_name: File name
15
- file_path: Full file path
16
- size: File size in bytes
17
- encoding: File encoding
18
- content: File content (base64 encoded for binary files)
19
- content_sha256: Content SHA256 hash
20
- ref: Git reference
21
- blob_id: Git blob ID
22
- commit_id: Last commit ID
23
- last_commit_id: Last commit affecting this file
24
"""
25
26
def save(self) -> None:
27
"""Save file changes (commit to repository)."""
28
29
def delete(self) -> None:
30
"""Delete file from repository."""
31
32
def decode(self) -> bytes:
33
"""Decode file content from base64."""
34
35
class ProjectFileManager(GetWithoutIdMixin[ProjectFile], CreateMixin[ProjectFile], UpdateMixin[ProjectFile], DeleteMixin[ProjectFile]):
36
"""Manager for repository files."""
37
38
def get(
39
self,
40
file_path: str,
41
ref: str = "main",
42
**kwargs
43
) -> ProjectFile:
44
"""
45
Get file content.
46
47
Parameters:
48
- file_path: Path to file in repository
49
- ref: Git reference (branch, tag, commit)
50
51
Returns:
52
ProjectFile object with content
53
"""
54
55
def create(self, data: dict, **kwargs) -> ProjectFile:
56
"""
57
Create new file.
58
59
Required fields:
60
- file_path: File path in repository
61
- branch: Target branch
62
- content: File content
63
- commit_message: Commit message
64
65
Optional fields:
66
- author_email: Author email
67
- author_name: Author name
68
- encoding: Content encoding ("text" or "base64")
69
- execute_filemode: Executable file mode
70
- start_branch: Start branch for new branch creation
71
"""
72
73
def update(self, file_path: str, data: dict, **kwargs) -> ProjectFile:
74
"""
75
Update existing file.
76
77
Parameters:
78
- file_path: File path in repository
79
- data: Update data
80
81
Required fields in data:
82
- branch: Target branch
83
- content: New file content
84
- commit_message: Commit message
85
86
Optional fields:
87
- author_email: Author email
88
- author_name: Author name
89
- encoding: Content encoding
90
- last_commit_id: Last known commit ID (for conflict detection)
91
- start_branch: Start branch for new branch creation
92
"""
93
94
def delete(self, file_path: str, data: dict, **kwargs) -> None:
95
"""
96
Delete file.
97
98
Parameters:
99
- file_path: File path to delete
100
- data: Deletion data
101
102
Required fields:
103
- branch: Target branch
104
- commit_message: Commit message
105
106
Optional fields:
107
- author_email: Author email
108
- author_name: Author name
109
- start_branch: Start branch for new branch creation
110
"""
111
112
def raw(self, file_path: str, ref: str = "main", **kwargs) -> bytes:
113
"""
114
Get raw file content.
115
116
Parameters:
117
- file_path: File path in repository
118
- ref: Git reference
119
120
Returns:
121
Raw file content as bytes
122
"""
123
124
def blame(self, file_path: str, ref: str = "main", **kwargs) -> list[dict]:
125
"""
126
Get file blame information.
127
128
Parameters:
129
- file_path: File path in repository
130
- ref: Git reference
131
132
Returns:
133
List of blame information for each line
134
"""
135
```
136
137
### Branch Management
138
139
```python { .api }
140
class ProjectBranch(ObjectDeleteMixin, RESTObject):
141
"""
142
Git branch object with protection and merge capabilities.
143
144
Key Attributes:
145
- name: Branch name
146
- merged: Merged status
147
- protected: Protected status
148
- default: Default branch flag
149
- developers_can_push: Developer push permission
150
- developers_can_merge: Developer merge permission
151
- can_push: Current user can push
152
- web_url: Branch web URL
153
- commit: Latest commit information
154
"""
155
156
def delete(self) -> None:
157
"""Delete branch."""
158
159
def protect(
160
self,
161
push_access_level: int = 40,
162
merge_access_level: int = 40,
163
unprotect_access_level: int = 40,
164
**kwargs
165
) -> dict:
166
"""
167
Protect branch.
168
169
Parameters:
170
- push_access_level: Push access level (30=Developer, 40=Maintainer)
171
- merge_access_level: Merge access level
172
- unprotect_access_level: Unprotect access level
173
174
Optional parameters:
175
- code_owner_approval_required: Require code owner approval
176
- allow_force_push: Allow force push
177
- allowed_to_push: List of users/groups allowed to push
178
- allowed_to_merge: List of users/groups allowed to merge
179
- allowed_to_unprotect: List of users/groups allowed to unprotect
180
181
Returns:
182
Dictionary with protection result
183
184
Raises:
185
GitlabProtectError: If protection fails
186
"""
187
188
def unprotect(self) -> dict:
189
"""
190
Unprotect branch.
191
192
Returns:
193
Dictionary with unprotection result
194
195
Raises:
196
GitlabProtectError: If unprotection fails
197
"""
198
199
class ProjectBranchManager(ListMixin[ProjectBranch], CreateMixin[ProjectBranch], DeleteMixin[ProjectBranch]):
200
"""Manager for project branches."""
201
202
def list(
203
self,
204
search: str | None = None,
205
regex: str | None = None,
206
**kwargs
207
) -> list[ProjectBranch]:
208
"""
209
List repository branches.
210
211
Parameters:
212
- search: Search pattern for branch names
213
- regex: Regex pattern for branch names
214
215
Returns:
216
List of ProjectBranch objects
217
"""
218
219
def create(self, data: dict, **kwargs) -> ProjectBranch:
220
"""
221
Create new branch.
222
223
Required fields:
224
- branch: New branch name
225
- ref: Source reference (branch, tag, commit)
226
227
Returns:
228
New ProjectBranch object
229
"""
230
231
class ProjectProtectedBranch(ObjectDeleteMixin, RESTObject):
232
"""
233
Protected branch configuration object.
234
235
Attributes:
236
- id: Protection rule ID
237
- name: Branch name pattern
238
- push_access_levels: Push access level rules
239
- merge_access_levels: Merge access level rules
240
- unprotect_access_levels: Unprotect access level rules
241
- code_owner_approval_required: Code owner approval requirement
242
- inherited: Inherited protection flag
243
- allow_force_push: Force push permission
244
"""
245
246
def delete(self) -> None:
247
"""Remove branch protection."""
248
249
class ProjectProtectedBranchManager(ListMixin[ProjectProtectedBranch], CreateMixin[ProjectProtectedBranch], DeleteMixin[ProjectProtectedBranch]):
250
"""Manager for protected branches."""
251
```
252
253
### Tag Management
254
255
```python { .api }
256
class ProjectTag(ObjectDeleteMixin, RESTObject):
257
"""
258
Git tag object with release information.
259
260
Key Attributes:
261
- name: Tag name
262
- message: Tag message
263
- target: Target commit SHA
264
- commit: Commit information
265
- release: Release information
266
- protected: Protected status
267
"""
268
269
def delete(self) -> None:
270
"""Delete tag."""
271
272
def set_release_description(self, description: str) -> dict:
273
"""
274
Set or update release description for tag.
275
276
Parameters:
277
- description: Release description
278
279
Returns:
280
Dictionary with release information
281
"""
282
283
class ProjectTagManager(ListMixin[ProjectTag], CreateMixin[ProjectTag], DeleteMixin[ProjectTag]):
284
"""Manager for project tags."""
285
286
def create(self, data: dict, **kwargs) -> ProjectTag:
287
"""
288
Create new tag.
289
290
Required fields:
291
- tag_name: Tag name
292
- ref: Source reference (branch, tag, commit)
293
294
Optional fields:
295
- message: Tag message
296
- release_description: Release description
297
298
Returns:
299
New ProjectTag object
300
"""
301
302
class ProjectProtectedTag(ObjectDeleteMixin, RESTObject):
303
"""Protected tag configuration."""
304
305
class ProjectProtectedTagManager(ListMixin[ProjectProtectedTag], CreateMixin[ProjectProtectedTag], DeleteMixin[ProjectProtectedTag]):
306
"""Manager for protected tags."""
307
```
308
309
### Commit Management
310
311
```python { .api }
312
class ProjectCommit(RESTObject):
313
"""
314
Git commit object with comprehensive information.
315
316
Key Attributes:
317
- id: Commit SHA
318
- short_id: Short commit SHA
319
- title: Commit title (first line of message)
320
- message: Full commit message
321
- author_name: Author name
322
- author_email: Author email
323
- authored_date: Author date
324
- committer_name: Committer name
325
- committer_email: Committer email
326
- committed_date: Commit date
327
- created_at: Creation timestamp
328
- parent_ids: Parent commit SHAs
329
- stats: Commit statistics (additions, deletions, total)
330
- status: Commit status
331
- last_pipeline: Last pipeline information
332
- web_url: Commit web URL
333
"""
334
335
def diff(self, **kwargs) -> list[dict]:
336
"""
337
Get commit diff.
338
339
Returns:
340
List of file diffs
341
"""
342
343
def comments(self, **kwargs) -> list[dict]:
344
"""Get commit comments."""
345
346
def comment(self, note: str, **kwargs) -> dict:
347
"""
348
Add comment to commit.
349
350
Parameters:
351
- note: Comment text
352
353
Optional parameters:
354
- path: File path for inline comment
355
- line: Line number for inline comment
356
- line_type: Line type ("new" or "old")
357
358
Returns:
359
Dictionary with comment information
360
"""
361
362
def cherry_pick(self, branch: str, **kwargs) -> dict:
363
"""
364
Cherry-pick commit to another branch.
365
366
Parameters:
367
- branch: Target branch name
368
369
Returns:
370
Dictionary with cherry-pick result
371
372
Raises:
373
GitlabCherryPickError: If cherry-pick fails
374
"""
375
376
def revert(self, branch: str, **kwargs) -> dict:
377
"""
378
Revert commit on specified branch.
379
380
Parameters:
381
- branch: Target branch name
382
383
Returns:
384
Dictionary with revert result
385
386
Raises:
387
GitlabRevertError: If revert fails
388
"""
389
390
class ProjectCommitManager(ListMixin[ProjectCommit], RetrieveMixin[ProjectCommit]):
391
"""Manager for project commits."""
392
393
def list(
394
self,
395
ref_name: str | None = None,
396
since: str | None = None,
397
until: str | None = None,
398
path: str | None = None,
399
author: str | None = None,
400
all: bool | None = None,
401
with_stats: bool | None = None,
402
first_parent: bool | None = None,
403
order: str | None = None,
404
trailers: bool | None = None,
405
**kwargs
406
) -> list[ProjectCommit]:
407
"""
408
List repository commits.
409
410
Parameters:
411
- ref_name: Branch or tag name
412
- since: Start date (ISO format)
413
- until: End date (ISO format)
414
- path: File path filter
415
- author: Author filter
416
- all: Include all branches
417
- with_stats: Include commit statistics
418
- first_parent: Only first parent commits
419
- order: Commit order ("default" or "topo")
420
- trailers: Include Git trailers
421
422
Returns:
423
List of ProjectCommit objects
424
"""
425
```
426
427
### Repository Information and Operations
428
429
```python { .api }
430
# Repository mixin provides repository-level operations
431
class RepositoryMixin:
432
"""Mixin providing repository operations."""
433
434
def repository_tree(
435
self,
436
path: str = "",
437
ref: str = "main",
438
recursive: bool = False,
439
get_all: bool = False,
440
**kwargs
441
) -> list[dict]:
442
"""
443
Get repository file tree.
444
445
Parameters:
446
- path: Directory path
447
- ref: Git reference
448
- recursive: Recursive listing
449
- get_all: Get all items (ignore pagination)
450
451
Returns:
452
List of tree items (files and directories)
453
"""
454
455
def repository_blob(self, sha: str, **kwargs) -> dict:
456
"""
457
Get blob content by SHA.
458
459
Parameters:
460
- sha: Blob SHA
461
462
Returns:
463
Dictionary with blob information and content
464
"""
465
466
def repository_archive(
467
self,
468
sha: str | None = None,
469
format: str = "tar.gz",
470
**kwargs
471
) -> bytes:
472
"""
473
Get repository archive.
474
475
Parameters:
476
- sha: Commit SHA (default: default branch)
477
- format: Archive format ("tar.gz", "tar.bz2", "tbz", "tbz2", "tb2", "bz2", "tar", "zip")
478
479
Returns:
480
Archive content as bytes
481
"""
482
483
def repository_compare(
484
self,
485
from_ref: str,
486
to_ref: str,
487
straight: bool = False,
488
**kwargs
489
) -> dict:
490
"""
491
Compare two references.
492
493
Parameters:
494
- from_ref: Source reference
495
- to_ref: Target reference
496
- straight: Straight comparison (no merge base)
497
498
Returns:
499
Dictionary with comparison information
500
"""
501
502
def repository_contributors(self, **kwargs) -> list[dict]:
503
"""
504
Get repository contributors.
505
506
Returns:
507
List of contributor information
508
"""
509
```
510
511
### Usage Examples
512
513
```python
514
import gitlab
515
516
gl = gitlab.Gitlab("https://gitlab.example.com", private_token="your-token")
517
project = gl.projects.get(123)
518
519
# File operations
520
# Get file content
521
try:
522
file = project.files.get("README.md", ref="main")
523
content = file.decode().decode('utf-8')
524
print(content)
525
except gitlab.GitlabGetError:
526
print("File not found")
527
528
# Create new file
529
file_data = {
530
"file_path": "new_file.py",
531
"branch": "main",
532
"content": "# New Python file\nprint('Hello World')",
533
"commit_message": "Add new Python file",
534
"author_name": "Developer",
535
"author_email": "dev@example.com"
536
}
537
new_file = project.files.create(file_data)
538
539
# Update file
540
update_data = {
541
"branch": "main",
542
"content": "# Updated content\nprint('Hello Updated World')",
543
"commit_message": "Update Python file"
544
}
545
project.files.update("new_file.py", update_data)
546
547
# Delete file
548
delete_data = {
549
"branch": "main",
550
"commit_message": "Remove Python file"
551
}
552
project.files.delete("new_file.py", delete_data)
553
554
# Get raw file content
555
raw_content = project.files.raw("README.md", ref="main")
556
557
# Get file blame
558
blame = project.files.blame("src/main.py", ref="main")
559
560
# Branch management
561
branches = project.branches.list(search="feature")
562
563
# Create branch
564
branch_data = {
565
"branch": "new-feature",
566
"ref": "main"
567
}
568
new_branch = project.branches.create(branch_data)
569
570
# Protect branch
571
branch = project.branches.get("main")
572
branch.protect(
573
push_access_level=40, # Maintainer
574
merge_access_level=30, # Developer
575
code_owner_approval_required=True,
576
allow_force_push=False
577
)
578
579
# Tag management
580
tags = project.tags.list()
581
582
# Create tag
583
tag_data = {
584
"tag_name": "v1.0.0",
585
"ref": "main",
586
"message": "Version 1.0.0 release",
587
"release_description": "First stable release"
588
}
589
new_tag = project.tags.create(tag_data)
590
591
# Commit operations
592
commits = project.commits.list(
593
ref_name="main",
594
since="2024-01-01T00:00:00Z",
595
with_stats=True
596
)
597
598
commit = project.commits.get("abc123")
599
diff = commit.diff()
600
commit.comment("Great commit!")
601
602
# Cherry-pick commit
603
commit.cherry_pick("develop")
604
605
# Repository operations
606
# Get repository tree
607
tree = project.repository_tree(path="src", recursive=True)
608
609
# Get repository archive
610
archive = project.repository_archive(format="zip")
611
with open("repo.zip", "wb") as f:
612
f.write(archive)
613
614
# Compare references
615
comparison = project.repository_compare("v1.0.0", "main")
616
print(f"Commits ahead: {len(comparison['commits'])}")
617
618
# Get contributors
619
contributors = project.repository_contributors()
620
for contributor in contributors:
621
print(f"{contributor['name']}: {contributor['commits']} commits")
622
```
623
624
### Error Handling
625
626
```python { .api }
627
class GitlabProtectError(GitlabOperationError):
628
"""Raised when branch/tag protection operation fails."""
629
pass
630
631
class GitlabCherryPickError(GitlabOperationError):
632
"""Raised when cherry-pick operation fails."""
633
pass
634
635
class GitlabRevertError(GitlabOperationError):
636
"""Raised when revert operation fails."""
637
pass
638
```
639
640
Example error handling:
641
```python
642
try:
643
file = project.files.get("nonexistent.txt")
644
except gitlab.GitlabGetError as e:
645
if e.response_code == 404:
646
print("File not found")
647
648
try:
649
branch.protect(push_access_level=30)
650
except gitlab.GitlabProtectError as e:
651
print(f"Cannot protect branch: {e}")
652
653
try:
654
commit.cherry_pick("target-branch")
655
except gitlab.GitlabCherryPickError as e:
656
print(f"Cherry-pick failed: {e}")
657
```