0
# Git Integration
1
2
Handle git merge conflicts and notebook-specific version control concerns. nbdev provides specialized tools for managing notebooks in git repositories, resolving merge conflicts, and maintaining clean version control history.
3
4
## Capabilities
5
6
### Merge Conflict Resolution
7
8
Resolve git merge conflicts in notebook files automatically.
9
10
```python { .api }
11
def nbdev_merge():
12
"""
13
Merge notebooks with conflict resolution.
14
15
Automatically resolves common notebook merge conflicts by:
16
- Combining cell outputs intelligently
17
- Resolving execution count conflicts
18
- Merging metadata changes
19
- Preserving both sets of changes where possible
20
"""
21
22
def nbdev_fix():
23
"""
24
Fix notebook merge conflicts.
25
26
Repairs notebook files that have git merge conflict markers,
27
attempting to create valid notebook JSON while preserving
28
both versions of conflicting content.
29
"""
30
```
31
32
**Usage Examples:**
33
34
```python
35
from nbdev.merge import nbdev_merge, nbdev_fix
36
37
# After git merge with conflicts
38
nbdev_merge() # Attempt automatic resolution
39
40
# If manual intervention needed
41
nbdev_fix() # Fix remaining conflicts
42
```
43
44
### Patch Management
45
46
Handle code patches and modifications in version control.
47
48
```python { .api }
49
def unpatch():
50
"""
51
Remove patches from code.
52
53
Removes temporary patches or modifications that were applied
54
for testing or development but shouldn't be permanent.
55
"""
56
```
57
58
### Configuration Regex
59
60
Utilities for handling configuration and merge patterns.
61
62
```python { .api }
63
def conf_re():
64
"""
65
Configuration regex patterns.
66
67
Returns:
68
Regex patterns for identifying configuration sections
69
and merge conflict markers in notebook files.
70
"""
71
```
72
73
## Git Workflow Integration
74
75
### Standard Git Operations
76
77
nbdev enhances standard git operations for notebooks:
78
79
```bash
80
# Before committing
81
nbdev_clean # Clean notebooks
82
git add .
83
git commit -m "Update notebooks"
84
85
# After pulling changes
86
git pull
87
nbdev_merge # Resolve any notebook conflicts
88
nbdev_update # Sync notebooks with code changes
89
```
90
91
### Merge Conflict Resolution Process
92
93
1. **Automatic Resolution**: `nbdev_merge()` attempts to resolve conflicts
94
2. **Manual Review**: Check remaining conflicts in notebook files
95
3. **Fix Remaining**: Use `nbdev_fix()` for stubborn conflicts
96
4. **Validation**: Ensure notebooks are valid JSON
97
5. **Testing**: Run `nbdev_test()` to verify functionality
98
99
```python
100
from nbdev.merge import nbdev_merge, nbdev_fix
101
from nbdev.test import nbdev_test
102
from nbdev.clean import nbdev_clean
103
104
def resolve_notebook_conflicts():
105
"""Complete workflow for resolving notebook merge conflicts."""
106
107
print("Attempting automatic merge resolution...")
108
nbdev_merge()
109
110
print("Fixing remaining conflicts...")
111
nbdev_fix()
112
113
print("Cleaning resolved notebooks...")
114
nbdev_clean()
115
116
print("Testing resolved notebooks...")
117
success = nbdev_test()
118
119
if success:
120
print("✓ Merge conflicts resolved successfully")
121
else:
122
print("⚠ Manual review needed - some tests failed")
123
124
return success
125
126
# Use after git merge conflicts
127
resolve_notebook_conflicts()
128
```
129
130
## Conflict Types and Resolution
131
132
### Common Notebook Conflicts
133
134
**Execution Count Conflicts:**
135
```json
136
<<<<<<< HEAD
137
"execution_count": 15,
138
=======
139
"execution_count": 23,
140
>>>>>>> branch
141
```
142
Resolution: Remove execution counts (they're not meaningful)
143
144
**Cell Output Conflicts:**
145
```json
146
<<<<<<< HEAD
147
"outputs": [{"text": "Result A"}],
148
=======
149
"outputs": [{"text": "Result B"}],
150
>>>>>>> branch
151
```
152
Resolution: Keep both outputs or choose based on context
153
154
**Metadata Conflicts:**
155
```json
156
<<<<<<< HEAD
157
"metadata": {"tags": ["important"]},
158
=======
159
"metadata": {"tags": ["test"]},
160
>>>>>>> branch
161
```
162
Resolution: Merge metadata or choose appropriate version
163
164
### Automated Resolution Strategies
165
166
nbdev uses intelligent strategies for different conflict types:
167
168
- **Execution counts**: Always removed (meaningless for version control)
169
- **Cell IDs**: Regenerated to avoid conflicts
170
- **Outputs**: Cleared or merged based on configuration
171
- **Source code**: Manual resolution required (most important)
172
- **Metadata**: Merged where possible, otherwise manual resolution
173
174
## Git Hooks Integration
175
176
### Pre-commit Hooks
177
178
Automatically clean notebooks before commits:
179
180
```bash
181
# Installed via nbdev_install_hooks()
182
# Pre-commit hook runs:
183
nbdev_clean --clear_all
184
```
185
186
### Post-merge Hooks
187
188
Automatically handle notebook updates after merges:
189
190
```bash
191
# Post-merge hook runs:
192
nbdev_merge
193
nbdev_update
194
```
195
196
## Advanced Git Operations
197
198
### Branch Management
199
200
```python
201
from nbdev.merge import nbdev_merge
202
from nbdev.export import nb_export
203
204
def safe_branch_switch(branch_name):
205
"""Safely switch branches with notebook handling."""
206
207
# Clean current state
208
nb_export() # Export current work
209
210
# Switch branches
211
import subprocess
212
subprocess.run(['git', 'checkout', branch_name])
213
214
# Handle any conflicts
215
nbdev_merge()
216
217
print(f"Switched to {branch_name} with notebooks updated")
218
219
safe_branch_switch('feature-branch')
220
```
221
222
### Repository Maintenance
223
224
```python
225
from nbdev.merge import nbdev_fix
226
from nbdev.clean import nbdev_clean
227
228
def maintain_notebook_repo():
229
"""Maintain notebook repository health."""
230
231
# Fix any lingering issues
232
nbdev_fix()
233
234
# Clean all notebooks
235
nbdev_clean(clear_all=True)
236
237
# Verify repository state
238
import subprocess
239
result = subprocess.run(['git', 'status', '--porcelain'],
240
capture_output=True, text=True)
241
242
if result.stdout.strip():
243
print("Repository has changes after maintenance:")
244
print(result.stdout)
245
else:
246
print("✓ Repository clean after maintenance")
247
248
maintain_notebook_repo()
249
```
250
251
## Integration with GitHub
252
253
### Pull Request Workflows
254
255
```python
256
# Before creating PR
257
from nbdev.clean import nbdev_clean
258
from nbdev.export import nb_export
259
from nbdev.test import nbdev_test
260
261
def prepare_pr():
262
"""Prepare notebooks for pull request."""
263
264
# Clean notebooks
265
nbdev_clean()
266
267
# Export to ensure code is up to date
268
nb_export()
269
270
# Run tests
271
if nbdev_test():
272
print("✓ Ready for pull request")
273
return True
274
else:
275
print("✗ Tests failed - fix before PR")
276
return False
277
278
prepare_pr()
279
```
280
281
### Collaborative Development
282
283
```python
284
from nbdev.merge import nbdev_merge
285
from nbdev.sync import nbdev_update
286
287
def sync_with_team():
288
"""Sync notebooks with team changes."""
289
290
# Pull latest changes
291
import subprocess
292
subprocess.run(['git', 'pull'])
293
294
# Resolve any notebook conflicts
295
nbdev_merge()
296
297
# Update notebooks with code changes
298
nbdev_update()
299
300
print("✓ Synced with team changes")
301
302
sync_with_team()
303
```
304
305
## Best Practices
306
307
### Version Control Strategy
308
309
1. **Always clean before committing**: Use `nbdev_clean()`
310
2. **Resolve conflicts immediately**: Don't let them accumulate
311
3. **Test after merges**: Run `nbdev_test()` after conflict resolution
312
4. **Use meaningful commit messages**: Describe notebook changes clearly
313
314
### Team Collaboration
315
316
```python
317
# Recommended team workflow
318
def team_workflow():
319
"""Recommended workflow for team collaboration."""
320
321
# Before starting work
322
subprocess.run(['git', 'pull'])
323
nbdev_merge() # Handle any conflicts
324
nbdev_update() # Update notebooks
325
326
# After making changes
327
nbdev_clean() # Clean notebooks
328
nb_export() # Export code
329
nbdev_test() # Test changes
330
331
# Before committing
332
subprocess.run(['git', 'add', '.'])
333
subprocess.run(['git', 'commit', '-m', 'Update notebooks'])
334
subprocess.run(['git', 'push'])
335
```
336
337
### Repository Setup
338
339
```bash
340
# Initial repository setup
341
nbdev_install_hooks # Install git hooks
342
git config merge.ours.driver true # For binary files
343
```
344
345
**Complete Git Integration Example:**
346
347
```python
348
from nbdev.merge import nbdev_merge, nbdev_fix
349
from nbdev.clean import nbdev_clean
350
from nbdev.test import nbdev_test
351
import subprocess
352
353
def complete_git_workflow():
354
"""Complete git workflow with notebook handling."""
355
356
print("1. Pulling latest changes...")
357
subprocess.run(['git', 'pull'])
358
359
print("2. Resolving notebook conflicts...")
360
nbdev_merge()
361
nbdev_fix()
362
363
print("3. Cleaning notebooks...")
364
nbdev_clean()
365
366
print("4. Running tests...")
367
if not nbdev_test():
368
print("Tests failed - manual review needed")
369
return False
370
371
print("5. Git workflow complete!")
372
return True
373
374
complete_git_workflow()
375
```