Skip to content

feat: add --init and --commit flags for git initialization after clone#63

Open
bryanprimus wants to merge 11 commits intonrjdalal:mainfrom
bryanprimus:feat/add-init-commit-option-after-cloning
Open

feat: add --init and --commit flags for git initialization after clone#63
bryanprimus wants to merge 11 commits intonrjdalal:mainfrom
bryanprimus:feat/add-init-commit-option-after-cloning

Conversation

@bryanprimus
Copy link
Copy Markdown

adds two new CLI flags that let users initialize a git repository and optionally
create an initial commit immediately after cloning with no extra manual steps needed.

closes #61

Motivation

gitpick intentionally strips the .git directory when cloning, which is great
for scaffolding. But users who want to immediately start tracking their own changes
had to manually run git init (and optionally git add . && git commit) after
every clone. This PR adds support to automate that workflow.

Changes

--init (boolean)

Initializes the target directory as a new git repository after cloning.

  • For tree/repo clones: runs git init inside the target directory.
  • For blob clones: runs git init in the parent directory (the natural repo root).
  • Skips silently if a .git directory already exists (idempotent).

--commit <msg> / -m <msg> (string)

Stages all cloned files and creates an initial git commit with the provided message.

  • Implies --init -> no need to pass both flags.
  • Runs git add . then git commit -m <msg> after initialization.

Usage

# Initialize as a git repo, commit later yourself
gitpick owner/repo --init

# Initialize and immediately create an initial commit
gitpick owner/repo --init --commit "Initial commit"

# --commit alone implies --init
gitpick owner/repo --commit "feat: scaffold from template"
gitpick owner/repo/tree/main/src -m "chore: add base source"

# Works with blob clones too (commits from parent dir)
gitpick owner/repo/blob/main/file.txt ./dest/file.txt --commit "feat: add config"

@nrjdalal
Copy link
Copy Markdown
Owner

Review

Overview

Adds --init (runs git init) and --commit <msg> / -m (implies --init, then git add . && git commit -m) after clone. For blob clones, the repo is initialized in the parent of the target file. Documented in README.md + --help, wired at all four clone call sites (local interactive copy, remote interactive pick, watch loop, and single clone), with four new tests.

Strengths

  • Small, well-scoped change with a single helper initGitRepo reused everywhere.
  • Idempotent git init (skips if .git already exists).
  • Sensible blob handling — git init in the file's parent directory.
  • README, --help, and tests all updated together.

Issues / Risks

1. Watch mode will fail on the second tick (bin/index.ts:656).
setInterval calls initGitRepo on every tick. git init is guarded by the .git check, but git commit -m ... is not — on iteration 2 with no changes you'll get nothing to commit, working tree clean and spawn will throw, killing the watcher. Even if there are changes, this produces an unexpected commit per interval. Suggest gating --commit so it runs only the first time (e.g., skip commit if HEAD already exists, or run init/commit outside the interval).

2. git commit requires user.name / user.email.
If the user has no git identity configured globally, the command errors out after a successful clone — surprising since the primary action succeeded. Consider catching the spawn error and printing a friendly hint (✖ git commit failed — configure user.name / user.email), or at least a try/catch that doesn't bubble a non-zero exit.

3. Blob target without a directory pollutes CWD.
gitpick owner/repo/blob/main/file.txt file.txt --initpath.dirname(\"file.txt\") is \".\", so git init runs in the user's current directory. That is almost certainly not what they want. Worth either warning, or requiring an explicit directory for blob + --init.

4. Hard-coded \"repository\" at two call sites (bin/index.ts:411, :593).
initGitRepo(targetDir, \"repository\", options) is passed in the interactive branches, but the helper's type parameter is typed as string. Tighten to \"blob\" | \"repository\" (or reuse config[\"type\"]) so the call sites don't silently drift.

5. git add . semantics for blob into non-empty directory.
git add . picks up anything in the spawn's cwd. For a blob clone into an existing non-empty directory (parent had other files before the clone), those unrelated files get staged and committed too. Probably fine given the scaffolding framing, but worth calling out in the README.

6. Help-text alignment.
-m, --commit <msg> is wider than the other two-column flags, so the description column shifts. Minor cosmetic.

Tests

Four new tests cover tree/blob × init/commit happy paths. Gaps worth adding:

  • Idempotency: calling --init when .git already exists should not error.
  • Watch mode: assert no crash on the second tick (related to Test #1).
  • --commit without git user config — confirms the error surface.

Security

options.commit flows into spawn(\"git\", [\"commit\", \"-m\", options.commit]) as an argv element, not a shell string — no injection risk. 👍

Recommendation

Approve after addressing #1 (watch-mode re-commit) and #2 (graceful failure when git identity is unset). The other items are polish.

@nrjdalal
Copy link
Copy Markdown
Owner

nrjdalal commented Apr 21, 2026

One more thought: there's no default commit message right now — commit is typed as string in parseArgs, so passing --commit / -m without a value errors out. Could we default it to "init awesomeness" when the flag is passed bare? Makes the zero-friction path even smoother:

gitpick owner/repo --commit   # → "init awesomeness"

@bryanprimus
Copy link
Copy Markdown
Author

Thanks for the review!! I've pushed updates addressing all your points:

  1. Watch mode: Moved initGitRepo outside the watch interval so it only runs once.
  2. Missing git identity: Wrapped git commit in a try/catch. It now prints a friendly warning instead of crashing the successful clone.
  3. CWD pollution: Added a guard to gracefully skip git init and show a warning if a user tries to clone a blob directly into the CWD with --init.
  4. Hard coded types: Refactored initGitRepo to check the actual filesystem (fs.statSync) instead of passing around type strings. This removes the hardcoded "repository" strings entirely and makes it much safer.
  5. git add . semantics: Added a note in the README clarifying this behavior when cloning into existing directories.
  6. Help text alignment: Fixed the spacing in both the CLI output and README.
  7. Default commit message: Implemented the "init awesomeness" default! Since Node's util.parseArgs doesn't support optional string flags, I added a tiny pre-parse step to inject the default value if --commit is passed bare.
  8. Tests: Added the requested tests in cli.test.ts covering idempotency, the watch mode second tick, and the missing git config error surface.

Let me know if something is still missing. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Option to Initialize Git Repository After Cloning

2 participants