diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml new file mode 100644 index 0000000..aa622e1 --- /dev/null +++ b/.github/workflows/github-pages.yml @@ -0,0 +1,89 @@ +name: Deploy Documentation to GitHub Pages + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build: + name: Build Documentation + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: ๐ฆ Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev + + - name: Cache Cargo + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-pages-${{ hashFiles('**/Cargo.lock') }} + + - name: ๐ฆ Build project + run: cargo build --release + + - name: ๐ Generate documentation + run: | + # Set environment variables to prevent browser opening + export GIT_EDITOR_NO_BROWSER=1 + export NO_BROWSER=1 + + # Create docs directory + mkdir -p docs-site + + # Generate the documentation HTML + cargo run --release -- --docs + + # Copy the generated HTML to docs-site directory + cp /tmp/git-editor-docs.html docs-site/index.html + + # Create a simple robots.txt for better SEO + echo -e "User-agent: *\nAllow: /" > docs-site/robots.txt + + # Create a .nojekyll file to bypass Jekyll processing + touch docs-site/.nojekyll + + - name: Setup Pages + uses: actions/configure-pages@v4 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: './docs-site' + + deploy: + name: Deploy to GitHub Pages + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + # Only deploy on pushes to main/master, not on PRs + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index fca8222..f114a2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -346,6 +346,7 @@ dependencies = [ "colored", "crossterm", "git2", + "open", "rand", "regex", "serial_test", @@ -538,6 +539,25 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -671,6 +691,17 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "open" +version = "5.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + [[package]] name = "openssl-probe" version = "0.1.6" @@ -712,6 +743,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + [[package]] name = "percent-encoding" version = "2.3.1" diff --git a/Cargo.toml b/Cargo.toml index 3b029f0..a98ec28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ url = "2.5.4" uuid = { version = "1.17.0", features = ["v4"] } crossterm = "0.27" tempfile = "3.0" +open = "5.0" [dev-dependencies] serial_test = "3.0" diff --git a/README.md b/README.md index 0cefd00..e776eaa 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,28 @@ cargo build --release # The binary will be available at target/release/git-editor ``` +## Documentation + +๐ **Comprehensive documentation is available online:** [rohansen856.github.io/git-editor](https://rohansen856.github.io/git-editor) + +The online documentation includes: +- Complete command reference with examples +- Technical implementation details +- Architecture overview and development guidelines +- Interactive copy-to-clipboard code examples +- Troubleshooting guide and FAQ +- Advanced usage patterns and best practices + +### Quick Access to Documentation + +You can also access the documentation directly from the command line: + +```bash +git-editor --docs +``` + +This command will generate and open the comprehensive documentation in your default browser. + ## Usage Git Editor supports five main modes of operation: diff --git a/docs/template.html b/docs/template.html new file mode 100644 index 0000000..6589f61 --- /dev/null +++ b/docs/template.html @@ -0,0 +1,1669 @@ + + + +
+ + +Git Editor is a sophisticated command-line tool written in Rust for comprehensive Git commit history manipulation. It provides surgical precision for rewriting timestamps, author information, and commit messages while maintaining repository integrity.
+ +# Download the latest release for your platform
+wget https://github.com/rohansen856/git-editor/releases/latest/download/git-editor-linux-x64.tar.gz
+tar -xzf git-editor-linux-x64.tar.gz
+sudo mv git-editor /usr/local/bin/
+
+# Verify installation
+git-editor --help
+ # Prerequisites: Rust 1.70+ and Git
+rustup update stable
+
+# Clone and build
+git clone https://github.com/rohansen856/git-editor.git
+cd git-editor
+
+# Build release binary
+cargo build --release
+
+# Install globally
+sudo cp target/release/git-editor /usr/local/bin/
+
+# Or use cargo install
+cargo install --path .
+ # Build Docker image
+docker build -t git-editor .
+
+# Run with repository mounted
+docker run -v /path/to/repo:/workspace git-editor --repo-path /workspace --docs
+ Git Editor operates in distinct modes, each optimized for specific use cases:
+ +| Mode | +Primary Flag | +Description | +Use Case | +Required Args | +
|---|---|---|---|---|
| Full Rewrite | +Default | +Complete repository history rewriting | +Bulk timestamp and author updates | +name, email, begin, end | +
| Show History | +-s, --show-history |
+ Display commit history without modifications | +Repository analysis and planning | +repo-path only | +
| Pick Specific | +-p, --pick-specific-commits |
+ Interactive individual commit selection | +Targeted commit modifications | +repo-path only | +
| Range Edit | +-x, --range |
+ Select and edit commit ranges | +Batch editing of consecutive commits | +repo-path only | +
| Simulation | +--simulate |
+ Preview changes without applying | +Safe testing and validation | +Depends on base mode | +
| Documentation | +--docs |
+ Open comprehensive documentation | +Help and reference | +None | +
Precedence Order (highest to lowest):
+--docs - Always takes precedence--show-history - Read-only operations--pick-specific-commits - Interactive selection--range - Range-based editing--simulate - Dry-run mode (applies to other modes)| Argument | +Short | +Type | +Description | +Example | +Required | +
|---|---|---|---|---|---|
--repo-path |
+ -r |
+ String | +Local path or Git URL to repository | +-r /path/to/repo-r https://github.com/user/repo.git |
+ โ (defaults to ./) | +
--email |
+ - | +Author email address (RFC 5322 compliant) | +--email user@example.com |
+ โ (full rewrite only) | +|
--name |
+ -n |
+ String | +Author display name | +-n "John Doe" |
+ โ (full rewrite only) | +
--begin |
+ -b |
+ DateTime | +Start timestamp (YYYY-MM-DD HH:MM:SS) | +-b "2023-01-01 09:00:00" |
+ โ (full rewrite only) | +
--end |
+ -e |
+ DateTime | +End timestamp (YYYY-MM-DD HH:MM:SS) | +-e "2023-12-31 17:00:00" |
+ โ (full rewrite only) | +
| Flag | +Short | +Description | +Conflicts With | +Additional Options | +
|---|---|---|---|---|
--show-history |
+ -s |
+ Display repository commit history | +All other modes | +None | +
--pick-specific-commits |
+ -p |
+ Interactive commit selection | +Full rewrite, range mode | +None | +
--range |
+ -x |
+ Range-based commit editing | +Full rewrite, pick mode | +--message, --author, --time |
+
--simulate |
+ - | +Dry-run mode (preview only) | +None (modifier) | +--show-diff |
+
--docs |
+ - | +Open documentation in browser | +All other modes | +None | +
These flags work exclusively with --range mode:
| Flag | +Description | +Effect | +
|---|---|---|
--message |
+ Edit only commit messages | +Preserves author and timestamp | +
--author |
+ Edit only author information | +Preserves message and timestamp | +
--time |
+ Edit only timestamps | +Preserves message and author | +
--range, all fields (message, author, timestamp) will be editable.
+ | Flag | +Description | +Output | +Requires | +
|---|---|---|---|
--show-diff |
+ Show detailed change preview | +Before/after comparison for each commit | +--simulate |
+
Git Editor uses a sophisticated algorithm for timestamp distribution:
+# Git Editor performs these validations:
+1. Repository existence and accessibility
+2. .git directory structure integrity
+3. Current branch and HEAD validity
+4. Working directory clean state check
+5. Remote tracking branch analysis
+ # Internal rewriting workflow:
+1. Create temporary branch for operations
+2. Walk commit history from oldest to newest
+3. Apply filter-branch-like operations with git2
+4. Maintain parent-child relationships
+5. Update branch references atomically
+6. Cleanup temporary objects
+ https://github.com/user/repo.gitgit@github.com:user/repo.githttp://example.com/repo.git| Repository Size | +Commit Count | +Processing Time | +Memory Usage | +
|---|---|---|---|
| Small (<10MB) | +<1,000 | +<10 seconds | +<50MB | +
| Medium (10-100MB) | +1,000-10,000 | +10-60 seconds | +50-200MB | +
| Large (100MB-1GB) | +10,000-100,000 | +1-10 minutes | +200MB-1GB | +
| Enterprise (>1GB) | +>100,000 | +>10 minutes | +>1GB | +
git-editor --docs
+ Opens this comprehensive documentation in your default browser.
+# Show history of current directory
+git-editor -s
+
+# Analyze specific repository
+git-editor --repo-path /path/to/repo --show-history
+
+# Analyze remote repository
+git-editor -r https://github.com/user/repo.git -s
+ Displays comprehensive commit history without making any changes.
+git-editor \
+ --name "John Doe" \
+ --email john@example.com \
+ --begin "2023-01-01 09:00:00" \
+ --end "2023-12-31 17:00:00"
+ Rewrites all commits with new author info and timestamps distributed between the specified dates.
+git-editor \
+ --repo-path https://github.com/user/private-repo.git \
+ --name "Corporate Identity" \
+ --email corporate@company.com \
+ --begin "2023-06-01 08:00:00" \
+ --end "2023-06-30 18:00:00"
+ Clones a remote repository, rewrites history, and prepares for push-back.
+# Interactive commit picker
+git-editor --pick-specific-commits
+
+# With specific repository
+git-editor -r /path/to/repo --pick-specific-commits
+ Provides an interactive interface to select and edit individual commits.
+# Edit all fields in a range
+git-editor --range
+
+# Edit only commit messages
+git-editor --range --message
+
+# Edit only author information
+git-editor --range --author
+
+# Edit only timestamps
+git-editor --range --time
+
+# Multiple field editing
+git-editor --range --message --author
+ Select a range of commits (e.g., commits 5-11) and edit specific fields.
+# Basic simulation
+git-editor --simulate \
+ --name "Test User" \
+ --email test@example.com \
+ --begin "2023-01-01 09:00:00" \
+ --end "2023-01-31 17:00:00"
+
+# Detailed diff preview
+git-editor --simulate --show-diff \
+ --name "John Doe" \
+ --email john@example.com \
+ --begin "2023-06-01 08:00:00" \
+ --end "2023-06-30 18:00:00"
+ Previews all changes with detailed diffs without applying them.
+# Simulate specific commit selection
+git-editor --simulate --pick-specific-commits
+
+# Simulate range editing
+git-editor --simulate --range --message
+
+# Simulate with detailed output
+git-editor --simulate --show-diff --range --author
+ Simulation mode works with all other operation modes for safe testing.
+# Anonymize commit history
+git-editor \
+ --name "Anonymous Contributor" \
+ --email anonymous@privacy.local \
+ --begin "2023-01-01 00:00:00" \
+ --end "2023-12-31 23:59:59"
+
+# Corporate identity standardization
+git-editor \
+ --name "Development Team" \
+ --email dev-team@company.com \
+ --begin "2023-04-01 09:00:00" \
+ --end "2023-04-30 17:00:00"
+ Standardize or anonymize commit authorship for privacy or corporate compliance.
+# Compress 6 months of work into 1 month
+git-editor \
+ --name "Rapid Developer" \
+ --email rapid@dev.com \
+ --begin "2023-11-01 08:00:00" \
+ --end "2023-11-30 20:00:00"
+
+# Expand 1 week into 3 months
+git-editor \
+ --name "Consistent Contributor" \
+ --email consistent@dev.com \
+ --begin "2023-09-01 09:00:00" \
+ --end "2023-11-30 17:00:00"
+ Adjust project timelines for demos, portfolio presentation, or analysis.
+The interactive commit picker provides:
+Range editing supports:
+Simulation Mode provides:
+# Supported URL formats:
+https://github.com/user/repo.git
+https://github.com/user/repo
+git@github.com:user/repo.git
+https://gitlab.com/user/repo.git
+https://bitbucket.org/user/repo.git
+
+# URL normalization and validation
+# Automatic .git suffix handling
+# Repository name extraction for temporary directories
+ git-editor/
+โโโ src/
+โ โโโ main.rs # Entry point and mode dispatch
+โ โโโ args.rs # CLI argument parsing (clap)
+โ โโโ docs.rs # Documentation generation
+โ โโโ rewrite/
+โ โ โโโ mod.rs # Rewrite module exports
+โ โ โโโ rewrite_all.rs # Full history rewriting
+โ โ โโโ rewrite_specific.rs # Interactive commit selection
+โ โ โโโ rewrite_range.rs # Range-based editing
+โ โโโ utils/
+โ โโโ mod.rs # Utility module exports
+โ โโโ types.rs # Common types and aliases
+โ โโโ validator.rs # Input validation
+โ โโโ datetime.rs # Timestamp generation
+โ โโโ commit_history.rs# Git operations
+โ โโโ prompt.rs # User interaction
+โ โโโ git_clone.rs # Repository cloning
+โ โโโ git_config.rs # Git configuration
+โ โโโ simulation.rs # Dry-run functionality
+โโโ docs/
+โ โโโ template.html # Documentation template
+โโโ tests/
+โ โโโ integration_tests.rs # Integration test suite
+โโโ Cargo.toml # Dependencies and metadata
+โโโ Dockerfile # Container configuration
+โโโ Makefile # Build automation
+ | Crate | +Version | +Purpose | +Features Used | +
|---|---|---|---|
git2 |
+ 0.20+ | +Git repository operations | +Repository access, commit manipulation | +
clap |
+ 4.5+ | +Command-line argument parsing | +Derive API, help generation | +
chrono |
+ 0.4+ | +Date/time handling | +DateTime parsing, timezone support | +
colored |
+ 3.0+ | +Terminal output coloring | +ANSI color codes, cross-platform | +
tempfile |
+ 3.20+ | +Temporary directory management | +Auto-cleanup, secure temp files | +
open |
+ 5.0+ | +Browser launching | +Cross-platform file opening | +
url |
+ 2.5+ | +URL parsing and validation | +Git URL parsing | +
regex |
+ 1.11+ | +Pattern matching | +Email validation, date parsing | +
| Test Type | +Count | +Coverage | +Purpose | +
|---|---|---|---|
| Unit Tests | +78 | +Core logic | +Individual function validation | +
| Integration Tests | +20 | +CLI behavior | +End-to-end workflow testing | +
| Doc Tests | +0 | +Documentation | +Code example validation | +
# Development build (fast compilation)
+cargo build
+
+# Release build (optimized)
+cargo build --release
+
+# Run with arguments
+cargo run -- --help
+cargo run -- --repo-path . -s
+
+# Watch mode for development
+cargo watch -x "run -- --docs"
+ # Run all tests (98 total)
+cargo test
+
+# Run unit tests only (78 tests)
+cargo test --lib
+
+# Run integration tests only (20 tests)
+cargo test --test integration_tests
+
+# Run specific test with output
+cargo test --test integration_tests test_show_history_mode_integration -- --nocapture
+
+# Run tests without browser opening (for development)
+GIT_EDITOR_NO_BROWSER=1 cargo test --all
+ # Format code
+cargo fmt
+
+# Check formatting without changes
+cargo fmt --check
+
+# Run linter
+cargo clippy
+
+# Run linter with strict warnings (CI requirement)
+cargo clippy -- -D warnings
+
+# Security audit
+cargo audit
+
+# Check for outdated dependencies
+cargo outdated
+ # Build release binary
+make build
+
+# Run all tests
+make test
+
+# Check code formatting
+make fmt
+
+# Run clippy linter
+make lint
+
+# Run with default parameters
+make run
+
+# Run with custom environment variables
+make run-custom
+
+# Clean build artifacts
+make clean
+
+# Build Docker image
+make docker-build
+
+# Run in Docker container
+make docker-run
+
+# Install binary to /usr/local/bin
+make install
+
+# Show all available commands
+make help
+ cargo buildcargo runcargo test to ensure no regressionscargo fmt and cargo clippymake test--docsError: Repository not found at path: /invalid/path
+ Solutions:
+ls -la /path/to/repols -la /path/to/repo/.gitls -ld /path/to/repoError: Invalid start date format (expected YYYY-MM-DD HH:MM:SS): 2023-1-1
+ Solutions:
+YYYY-MM-DD HH:MM:SS2023-01-01 09:00:00Error: Invalid email format: user@domain
+ Solutions:
+user@domain.com"user name"@domain.comError: Authentication failed for Git URL
+ Solutions:
+git config --global credential.helper storessh-add ~/.ssh/id_rsagit clone first# For large repositories, consider:
+
+# 1. Use simulation mode first
+git-editor --simulate --show-diff [other-args]
+
+# 2. Process in smaller ranges
+git-editor --range --message # Edit specific fields only
+
+# 3. Monitor system resources
+htop # Watch memory and CPU usage
+
+# 4. Ensure sufficient disk space
+df -h # Check available space
+ Memory optimization tips:
+Answer: History rewriting is permanent. However, you can:
+Answer: Yes, Git Editor can clone and process remote repositories:
+Answer: Use with extreme caution:
+If you encounter issues:
+git-editor --docs// Get comprehensive commit history
+pub fn get_commit_history(args: &Args, print: bool) -> Result<Vec<CommitInfo>>
+
+// Analyze repository structure
+pub fn analyze_repository(repo_path: &str) -> Result<RepositoryStats>
+
+// Validate repository integrity
+pub fn validate_repository(repo_path: &str) -> Result<()>
+ // Generate realistic timestamp distribution
+pub fn generate_timestamps(
+ start: &str,
+ end: &str,
+ count: usize
+) -> Result<Vec<DateTime<Utc>>>
+
+// Create business-hour weighted distribution
+pub fn generate_business_hour_timestamps(
+ start: DateTime<Utc>,
+ end: DateTime<Utc>,
+ commit_count: usize
+) -> Vec<DateTime<Utc>>
+ // Full repository history rewrite
+pub fn rewrite_all_commits(args: &Args) -> Result<()>
+
+// Interactive commit selection and editing
+pub fn rewrite_specific_commits(args: &Args) -> Result<()>
+
+// Range-based commit editing
+pub fn rewrite_range_commits(args: &Args) -> Result<()>
+ pub struct CommitInfo {
+ pub hash: String, // Full SHA-1 hash
+ pub short_hash: String, // Abbreviated hash (7 chars)
+ pub timestamp: DateTime<Utc>, // Commit timestamp
+ pub author_name: String, // Author display name
+ pub author_email: String, // Author email address
+ pub message: String, // Commit message
+ pub parent_count: usize, // Number of parent commits
+}
+ pub struct EditOptions {
+ pub edit_author_name: bool, // Enable author name editing
+ pub edit_author_email: bool, // Enable author email editing
+ pub edit_timestamp: bool, // Enable timestamp editing
+ pub edit_message: bool, // Enable message editing
+ pub new_author_name: Option<String>,
+ pub new_author_email: Option<String>,
+ pub new_message: Option<String>,
+}
+ | Variable | +Purpose | +Default | +Example | +
|---|---|---|---|
GIT_EDITOR_NO_BROWSER |
+ Disable browser opening for docs | +Not set | +GIT_EDITOR_NO_BROWSER=1 |
+
NO_BROWSER |
+ Alternative browser disable flag | +Not set | +NO_BROWSER=1 |
+
RUST_LOG |
+ Logging level control | +Not set | +RUST_LOG=debug |
+
| Code | +Meaning | +Description | +
|---|---|---|
0 |
+ Success | +Operation completed successfully | +
1 |
+ General Error | +Unspecified error occurred | +
2 |
+ Invalid Arguments | +Command-line argument validation failed | +
3 |
+ Repository Error | +Git repository access or validation failed | +
4 |
+ Permission Error | +Insufficient permissions for operation | +