Skip to content

Commit e2dfc77

Browse files
committed
docs: add comprehensive guide for git history rewrite issues and solutions (refs #68)
1 parent 03cd8c0 commit e2dfc77

File tree

1 file changed

+233
-0
lines changed

1 file changed

+233
-0
lines changed

docs/GIT_HISTORY_REWRITE_ISSUES.md

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Git History Rewrite Issues and Solutions
2+
3+
## Overview
4+
5+
This document records issues encountered when using `git filter-repo` to rewrite git history and the solutions implemented to resolve them. This is particularly important for projects that use GitHub Actions for automated releases.
6+
7+
## Issue: GitHub Actions Using Old History After Git Filter-Repo
8+
9+
### Symptoms
10+
11+
1. **Local vs. GitHub Actions Discrepancy**:
12+
- Local repository shows correct commit count (e.g., 137 commits since v00.52.00)
13+
- GitHub Actions shows incorrect commit count (e.g., 398 commits since v00.52.00)
14+
15+
2. **Release Notes Generation Problems**:
16+
- Release notes include all issues from entire repository history
17+
- Issues from much earlier versions appear in recent release notes
18+
- Release notes are excessively long with hundreds of commits
19+
20+
3. **Tag Hash Mismatches**:
21+
- Local tag hash: `a0e7ead4ea13e3353eb8086faedbad596968ae1c`
22+
- GitHub Actions tag hash: `3c45f4ef25d4fc36b4ba8d5ffaa889b03c268192`
23+
24+
### Root Cause
25+
26+
When `git filter-repo` rewrites git history:
27+
28+
1. **New Commit Hashes**: All commit hashes change due to the rewrite
29+
2. **Tag References**: Tags still point to old commit hashes that no longer exist in the rewritten history
30+
3. **GitHub Caching**: GitHub may serve different versions of the repository to different clients
31+
4. **Incomplete Push**: The rewritten history and updated tags weren't fully pushed to GitHub
32+
33+
### Detection Methods
34+
35+
#### 1. Debug Output in Workflow
36+
37+
Add debug steps to GitHub Actions workflow to detect the issue:
38+
39+
```yaml
40+
- name: Verify Git History
41+
run: |
42+
echo "=== GIT HISTORY VERIFICATION ==="
43+
echo "Checking if we have the correct rewritten history..."
44+
45+
# Check if filter-repo evidence exists
46+
if [[ -d ".git/filter-repo" ]]; then
47+
echo "✅ Filter-repo evidence found - using rewritten history"
48+
else
49+
echo "❌ No filter-repo evidence found - may be using old history"
50+
fi
51+
52+
# Show commit range analysis
53+
echo ""
54+
echo "=== COMMIT RANGE ANALYSIS ==="
55+
echo "Total commits since v${{ inputs.prev_version }}:"
56+
git log --oneline v${{ inputs.prev_version }}..HEAD | wc -l
57+
echo ""
58+
echo "Unique issues referenced:"
59+
git log --oneline v${{ inputs.prev_version }}..HEAD | grep -o "(refs #[0-9]*)" | sort | uniq | wc -l
60+
```
61+
62+
#### 2. Tag Hash Verification
63+
64+
Compare local and remote tag hashes:
65+
66+
```bash
67+
# Local
68+
git rev-parse v00.52.00
69+
70+
# Check what GitHub Actions sees
71+
gh run view <run-id> --log | grep "Tag v00.52.00:"
72+
```
73+
74+
#### 3. Commit Count Comparison
75+
76+
Compare expected vs. actual commit counts:
77+
78+
```bash
79+
# Expected (local)
80+
git log --oneline v00.52.00..HEAD | wc -l
81+
82+
# Actual (workflow output)
83+
# Check workflow logs for commit count
84+
```
85+
86+
### Solutions
87+
88+
#### 1. Force Push Tags (Primary Solution)
89+
90+
After `git filter-repo`, force push all tags to update them on GitHub:
91+
92+
```bash
93+
# Force push all tags with rewritten history
94+
git push --force --tags
95+
96+
# Verify tag updates
97+
git push --force-with-lease --tags
98+
```
99+
100+
#### 2. Workflow Detection and Prevention
101+
102+
Add steps to GitHub Actions workflow to detect and prevent using old history:
103+
104+
```yaml
105+
- name: Force Rewritten History
106+
run: |
107+
echo "=== FORCING REWRITTEN HISTORY ==="
108+
109+
# Force fetch all refs to ensure we have the latest history
110+
git fetch --all --tags --force
111+
112+
# Verify we have the correct history
113+
echo "Current HEAD: $(git rev-parse HEAD)"
114+
echo "Tag v${{ inputs.prev_version }}: $(git rev-parse v${{ inputs.prev_version }})"
115+
116+
# Check if we're using the rewritten history
117+
if git log --oneline v${{ inputs.prev_version }}..HEAD | wc -l | grep -q "397"; then
118+
echo "❌ Still using old history (397 commits detected)"
119+
echo "Attempting to force rewritten history..."
120+
121+
# Try to fetch the rewritten history explicitly
122+
git fetch origin --force
123+
git reset --hard origin/main
124+
git fetch --all --tags --force
125+
126+
# Verify again
127+
COMMIT_COUNT=$(git log --oneline v${{ inputs.prev_version }}..HEAD | wc -l)
128+
echo "Commit count after force fetch: $COMMIT_COUNT"
129+
130+
if [[ $COMMIT_COUNT -gt 200 ]]; then
131+
echo "❌ Still using old history. Manual intervention required."
132+
echo "The repository may need to be re-pushed with the rewritten history."
133+
exit 1
134+
else
135+
echo "✅ Now using rewritten history"
136+
fi
137+
else
138+
echo "✅ Using rewritten history"
139+
fi
140+
```
141+
142+
#### 3. Improved Script Error Handling
143+
144+
Update release note generation scripts to fail on incorrect commit ranges:
145+
146+
```zsh
147+
# In generate-release-notes.zsh
148+
if ! git rev-parse "v${previous_version}" &>/dev/null; then
149+
print_error "Previous version tag v${previous_version} not found"
150+
print_error "Available tags:"
151+
git tag --list "v*" | head -10
152+
exit 1
153+
fi
154+
155+
# Verify commit range is reasonable
156+
local commit_count=$(git log --oneline "v${previous_version}..HEAD" | wc -l)
157+
if [[ $commit_count -gt 200 ]]; then
158+
print_warning "Large commit count detected: $commit_count"
159+
print_warning "This may indicate git history issues"
160+
print_warning "Expected: ~100-150 commits for recent releases"
161+
fi
162+
```
163+
164+
### Prevention Strategies
165+
166+
#### 1. Pre-Workflow Verification
167+
168+
Before running workflows, verify local and remote are in sync:
169+
170+
```bash
171+
# Check tag consistency
172+
git ls-remote --tags origin | grep v00.52.00
173+
git rev-parse v00.52.00
174+
175+
# Check commit count consistency
176+
git log --oneline v00.52.00..HEAD | wc -l
177+
```
178+
179+
#### 2. Workflow Validation
180+
181+
Add validation steps to workflows to catch issues early:
182+
183+
```yaml
184+
- name: Validate Git History
185+
run: |
186+
# Check for reasonable commit counts
187+
COMMIT_COUNT=$(git log --oneline v${{ inputs.prev_version }}..HEAD | wc -l)
188+
if [[ $COMMIT_COUNT -gt 200 ]]; then
189+
echo "❌ Unreasonable commit count: $COMMIT_COUNT"
190+
echo "This may indicate git history issues"
191+
exit 1
192+
fi
193+
```
194+
195+
#### 3. Documentation Requirements
196+
197+
- Document all git history rewrites
198+
- Record expected commit counts for each version range
199+
- Maintain a log of tag hash changes
200+
201+
### Related Issues
202+
203+
#### 1. Release Notes Generation
204+
205+
- **Problem**: Scripts fall back to `git log --all` when commit ranges fail
206+
- **Solution**: Improve error handling to fail fast instead of using fallbacks
207+
208+
#### 2. Parameter Validation
209+
210+
- **Problem**: Workflow scripts accept unknown parameters silently
211+
- **Solution**: Use strict parameter validation with `zparseopts`
212+
213+
### Lessons Learned
214+
215+
1. **Always force push tags** after `git filter-repo`
216+
2. **Verify tag consistency** between local and remote
217+
3. **Add detection mechanisms** in workflows to catch history issues
218+
4. **Fail fast** when git history looks suspicious
219+
5. **Document expected commit counts** for validation
220+
6. **Use strict parameter validation** in all scripts
221+
222+
### Future Improvements
223+
224+
1. **Automated History Validation**: Add pre-commit hooks to detect history issues
225+
2. **Tag Synchronization**: Automate tag verification and updates
226+
3. **Workflow Monitoring**: Add alerts for unusual commit counts
227+
4. **Documentation Automation**: Auto-generate history change logs
228+
229+
## References
230+
231+
- [Git Filter-Repo Documentation](https://github.com/newren/git-filter-repo)
232+
- [GitHub Actions Checkout Action](https://github.com/actions/checkout)
233+
- [Git Force Push Considerations](https://git-scm.com/docs/git-push#Documentation/git-push.txt---force)

0 commit comments

Comments
 (0)