-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add Git conflict marker detection #124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+319
−0
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # SPDX-FileCopyrightText: 2025 SecPal Contributors | ||
| # SPDX-License-Identifier: AGPL-3.0-or-later | ||
|
|
||
| name: Check for Merge Conflict Markers | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: [main] | ||
| push: | ||
| branches: [main] | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| check-conflicts: | ||
| name: Check for Git Conflict Markers | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Run conflict marker check | ||
| run: | | ||
| chmod +x scripts/check-conflict-markers.sh | ||
| ./scripts/check-conflict-markers.sh |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,196 @@ | ||
| <!-- | ||
| SPDX-FileCopyrightText: 2025 SecPal Contributors | ||
| SPDX-License-Identifier: CC0-1.0 | ||
| --> | ||
|
|
||
| # Git Conflict Marker Detection | ||
|
|
||
| The `check-conflict-markers.sh` script detects unresolved Git merge conflict markers in tracked files to prevent accidental commits of broken code. | ||
|
|
||
| ## Problem | ||
|
|
||
| When resolving merge conflicts, developers sometimes forget to remove conflict markers: | ||
|
|
||
| ```bash | ||
| <<<<<<< HEAD | ||
| code from current branch | ||
| ======= | ||
| code from incoming branch | ||
| >>>>>>> feature-branch | ||
| ``` | ||
|
|
||
| These markers cause: | ||
|
|
||
| - **Syntax errors** in source code | ||
| - **Runtime failures** in scripts and configuration files | ||
| - **Broken builds** in CI/CD pipelines | ||
| - **Production incidents** if deployed | ||
|
|
||
| ## Solution | ||
|
|
||
| This script automatically detects conflict markers in all tracked text files before they reach the repository. | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Manual Check | ||
|
|
||
| ```bash | ||
| # Check all tracked files | ||
| ./scripts/check-conflict-markers.sh | ||
| ``` | ||
|
|
||
| ### CI/CD Integration | ||
|
|
||
| The script runs automatically in CI via GitHub Actions on every PR and push to `main`. | ||
|
|
||
| ### Pre-commit Hook | ||
|
|
||
| Add to `.git/hooks/pre-commit`: | ||
|
|
||
| ```bash | ||
| #!/bin/bash | ||
| # Run conflict marker check | ||
| if [ -f scripts/check-conflict-markers.sh ]; then | ||
| ./scripts/check-conflict-markers.sh || exit 1 | ||
| fi | ||
| ``` | ||
|
|
||
| ## Detected Patterns | ||
|
|
||
| The script detects these conflict markers: | ||
|
|
||
| | Marker | Meaning | | ||
| | -------------------------- | ------------------------------- | | ||
| | `<<<<<<<` | Start of conflict (from HEAD) | | ||
| | `=======` | Separator between changes | | ||
| | `>>>>>>>` | End of conflict (from incoming) | | ||
| | `\|\|\|\|\|\|\|` (+ space) | Optional: diff3 style marker | | ||
|
|
||
| ## Exit Codes | ||
|
|
||
| - `0` - No conflict markers found ✅ | ||
| - `1` - Conflict markers detected ❌ | ||
|
|
||
| ## Example Output | ||
|
|
||
| ### Success (No Conflicts) | ||
|
|
||
| ```bash | ||
| ═══════════════════════════════════════════════════════════════ | ||
| Git Conflict Marker Detection | ||
| ═══════════════════════════════════════════════════════════════ | ||
|
|
||
| ───────────────────────────────────────────────────── | ||
| Checked files: 111 | ||
| ✓ No conflict markers found | ||
| ═══════════════════════════════════════════════════════════════ | ||
| ``` | ||
|
|
||
| ### Failure (Conflicts Found) | ||
|
|
||
| ```bash | ||
| ═══════════════════════════════════════════════════════════════ | ||
| Git Conflict Marker Detection | ||
| ═══════════════════════════════════════════════════════════════ | ||
|
|
||
| ✗ Conflict markers detected: | ||
|
|
||
| File: .git/hooks/pre-push | ||
| Line 73: <<<<<<< Updated upstream... | ||
|
|
||
| File: src/main.py | ||
| Line 42: =======... | ||
|
|
||
| ───────────────────────────────────────────────────── | ||
| Checked files: 111 | ||
| ✗ Found conflict markers in files | ||
|
|
||
| Action required: | ||
| 1. Open the affected files | ||
| 2. Search for conflict markers: <<<<<<<, =======, >>>>>>> | ||
| 3. Manually resolve the conflicts | ||
| 4. Remove all conflict markers | ||
| 5. Test your changes | ||
| 6. Commit again | ||
|
|
||
| ═══════════════════════════════════════════════════════════════ | ||
| ``` | ||
|
|
||
| ## How to Resolve Conflicts | ||
|
|
||
| 1. **Locate the markers** - The script shows file names and line numbers | ||
| 2. **Review both changes** - Understand code from both branches | ||
| 3. **Choose or merge** - Keep one version, the other, or combine both | ||
| 4. **Remove markers** - Delete all `<<<<<<<`, `=======`, `>>>>>>>` lines | ||
| 5. **Test** - Verify the code works correctly | ||
| 6. **Commit** - Try committing again | ||
|
|
||
| ## Common Scenarios | ||
|
|
||
| ### False Positives | ||
|
|
||
| The script only checks lines **starting with** conflict markers, reducing false positives. If you legitimately need these patterns in your code (e.g., documentation), indent them: | ||
|
|
||
| ```markdown | ||
| <!-- This is documentation, not a conflict --> | ||
|
|
||
| <<<<<<< This won't trigger (indented) | ||
| ``` | ||
|
|
||
| ### Binary Files | ||
|
|
||
| Binary files are automatically skipped - only text files are checked. | ||
|
|
||
| ### .git Directory | ||
|
|
||
| The `.git` directory itself is excluded from checks (uses `git ls-files`). | ||
|
|
||
| ## Integration with Other Tools | ||
|
|
||
| ### Pre-commit Framework | ||
|
|
||
| ```yaml | ||
| # .pre-commit-config.yaml | ||
| repos: | ||
| - repo: local | ||
| hooks: | ||
| - id: check-conflict-markers | ||
| name: Check for conflict markers | ||
| entry: ./scripts/check-conflict-markers.sh | ||
| language: script | ||
| pass_filenames: false | ||
| ``` | ||
|
|
||
| ### CI/CD Pipelines | ||
|
|
||
| ```yaml | ||
| # GitHub Actions (already included) | ||
| - name: Check conflict markers | ||
| run: ./scripts/check-conflict-markers.sh | ||
| ``` | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### "Permission denied" | ||
|
|
||
| ```bash | ||
| chmod +x scripts/check-conflict-markers.sh | ||
| ``` | ||
|
|
||
| ### "file: command not found" | ||
|
|
||
| Install the `file` utility: | ||
|
|
||
| ```bash | ||
| # Ubuntu/Debian | ||
| sudo apt install file | ||
|
|
||
| # macOS | ||
| brew install file | ||
| ``` | ||
|
|
||
| ## See Also | ||
|
|
||
| - [Preflight Script Documentation](PREFLIGHT.md) - Quality Gate Checks | ||
| - [System Requirements Check](CHECK_SYSTEM_REQUIREMENTS.md) - Development Prerequisites | ||
| - [Git Merge Conflicts](https://git-scm.com/docs/git-merge#_how_conflicts_are_presented) - Official Git Documentation |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| #!/usr/bin/env bash | ||
| # SPDX-FileCopyrightText: 2025 SecPal Contributors | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| # ============================================================================ | ||
| # Git Conflict Marker Detection | ||
| # ============================================================================ | ||
| # Detects unresolved Git merge conflict markers in tracked files to prevent | ||
| # accidental commits of broken code. | ||
| # | ||
| # Exit codes: | ||
| # 0 - No conflict markers found | ||
| # 1 - Conflict markers detected | ||
| # ============================================================================ | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| # Colors | ||
| RED='\033[0;31m' | ||
| GREEN='\033[0;32m' | ||
| YELLOW='\033[1;33m' | ||
| BLUE='\033[0;34m' | ||
| NC='\033[0m' # No Color | ||
|
|
||
| # Conflict marker patterns | ||
| MARKERS=( | ||
| "<<<<<<< " # Start of conflict (from HEAD) | ||
| "=======" # Separator between changes | ||
| ">>>>>>> " # End of conflict (from incoming) | ||
| "||||||| " # Optional: diff3 style marker | ||
| ) | ||
|
|
||
| CONFLICTS_FOUND=0 | ||
| CHECKED_FILES=0 | ||
|
|
||
| echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" | ||
| echo -e "${BLUE}Git Conflict Marker Detection${NC}" | ||
| echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" | ||
| echo "" | ||
|
|
||
| # Get list of tracked files (excluding .git directory) | ||
| while IFS= read -r -d '' file; do | ||
| # Skip binary files and non-text files | ||
| if file "$file" | grep -q "text"; then | ||
| CHECKED_FILES=$((CHECKED_FILES + 1)) | ||
|
|
||
| # Check each conflict marker pattern | ||
| for marker in "${MARKERS[@]}"; do | ||
| if grep -n "^${marker}" "$file" > /dev/null 2>&1; then | ||
| if [ $CONFLICTS_FOUND -eq 0 ]; then | ||
| echo -e "${RED}✗ Conflict markers detected:${NC}" | ||
| echo "" | ||
| fi | ||
|
|
||
| CONFLICTS_FOUND=$((CONFLICTS_FOUND + 1)) | ||
| echo -e "${YELLOW}File:${NC} $file" | ||
|
|
||
| # Show lines with conflict markers | ||
| grep -n "^${marker}" "$file" | while IFS=: read -r line_num line_content; do | ||
| echo -e " ${RED}Line $line_num:${NC} ${line_content:0:60}..." | ||
| done | ||
| echo "" | ||
| break # Only report once per file | ||
| fi | ||
| done | ||
| fi | ||
| done < <(git ls-files -z) | ||
|
|
||
| echo -e "${BLUE}─────────────────────────────────────────────────────${NC}" | ||
| echo -e "Checked files: ${CHECKED_FILES}" | ||
|
|
||
| if [ $CONFLICTS_FOUND -eq 0 ]; then | ||
| echo -e "${GREEN}✓ No conflict markers found${NC}" | ||
| echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" | ||
| exit 0 | ||
| else | ||
| echo -e "${RED}✗ Found conflict markers in files${NC}" | ||
| echo "" | ||
| echo -e "${YELLOW}Action required:${NC}" | ||
| echo "1. Open the affected files" | ||
| echo "2. Search for conflict markers: <<<<<<<, =======, >>>>>>>" | ||
| echo "3. Manually resolve the conflicts" | ||
| echo "4. Remove all conflict markers" | ||
| echo "5. Test your changes" | ||
| echo "6. Commit again" | ||
| echo "" | ||
| echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" | ||
| exit 1 | ||
| fi | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.