Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

2 Commits

Repository files navigation

gitpush

Push a folder of scripts or code to GitHub with one command. Pure Python — no git installation required, works anywhere Python runs (including iOS shells like a-Shell).

python gitpush.py push ./myscripts

That single command will:

  1. Turn the folder into a git repo (if it isn't one yet)
  2. Detect every new, changed, and deleted file
  3. Skip junk (__pycache__, .venv, node_modules, .pyc, .DS_Store, editor folders...)
  4. Commit everything
  5. Create the GitHub repo if it doesn't exist (named after the folder)
  6. Push

Install (one time)

pip install dulwich

Get a GitHub token (one time)

  1. Go to github.com → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token
  2. Repository access: All repositories (or select specific ones)
  3. Permissions:
    • Contents: Read and write — needed to push
    • Administration: Read and write — needed to auto-create repos
  4. Copy the token (github_pat_...)

Set your environment (each session, or add to ~/.profile)

export GITHUB_TOKEN=github_pat_yourtoken
export GITHUB_USER=yourusername
export GITHUB_EMAIL=you@example.com # optional, see belowexport GITPUSH_ROOT=~/Documents/projects # optional safety fence, see below

All are optional — if token or username is missing, gitpush simply asks you when it needs them. Setting them just skips the prompts.

GITHUB_EMAIL controls the author email on your commits. If unset, gitpush derives your GitHub noreply address from your username automatically — commits still link to your profile and count on your contribution graph, without exposing a real email.

First push of a new repo interactively asks for optional extras — description, website, topics — press Enter to skip any of them.

GITPUSH_ROOT is a safety fence: when set, gitpush refuses to push or pushall any folder outside that directory. Useful to guarantee you can never accidentally push your Downloads folder.

Ignoring things

Three layers keep junk out of your repos:

  1. Built-in filters__pycache__, .venv, node_modules, .pyc, .DS_Store, editor folders are always skipped (edit SKIP_PARTS etc. at the top of the script to change).
  2. .gitignore — Dulwich honors standard .gitignore files, same as regular git.
  3. .gitpushignore (or _gitpush_ignore.txt — handy on iOS, where dotfiles are awkward) — auto-created with a commented template on your first push or pushall in a folder, so you always have somewhere to add exclusions. One pattern per line, # for comments, wildcards allowed. The ignore file itself is never pushed to GitHub:
    • In a project folder: those files/folders are never staged by push.
    • In a parent folder: pushall skips those subfolders entirely.
# _gitpush_ignore.txt in ~/Documents
models
experiments
*.bin

pushall also lists every folder → repo mapping and asks for confirmation before touching anything (-y skips the prompt for scripting).

Commands

CommandWhat it does
push FOLDERThe main one: commit everything + push. Creates the GitHub repo if needed.
status FOLDERList what would be pushed, change nothing
log FOLDERShow recent commits
pushall FOLDERPush every subfolder to its own repo in one go (same flags as push)
pull FOLDER or pull user/nameFetch + merge the latest from GitHub (clones if you don't have it yet)
clone user/nameCopy a GitHub repo down
create NAMECreate an empty repo on GitHub (rarely needed — push does it)
init FOLDERMake a folder a git repo without pushing (rarely needed — push does it)

Flags

FlagWorks onMeaningDefault
-r, --repopush, pull, cloneTarget repo. name or user/name$GITHUB_USER/foldername
-m, --messagepushCommit messagemade some changes
-n, --dry-runpushPreview only, touch nothingoff
-p, --privatepush, createMake auto-created repo privatepublic
-f, --forcepush, pushallForce push - overwrite remote history (use after rewriting local history)off
-y, --yespushallSkip the are-you-sure confirmationoff
-b, --branchpush, pullBranch to usemain
-t, --tokenall remote commandsToken override$GITHUB_TOKEN or prompt
-c, --countlogHow many commits to show10

Examples

# Push a folder - repo "myscripts" is created automatically if missing
python gitpush.py push ./myscripts
# Same, but with a proper commit message
python gitpush.py push ./myscripts -m "add backup script"# Push to a repo with a different name than the folder
python gitpush.py push ./myscripts -r utilities
python gitpush.py push ./myscripts -r someoneelse/shared-repo
# Auto-create as a PRIVATE repo on first push
python gitpush.py push ./secrets-lab -p
# See what would be pushed without doing anything
python gitpush.py push ./myscripts -n
# Check for unpushed changes / recent history
python gitpush.py status ./myscripts
python gitpush.py log ./myscripts -c 5
# Get a repo onto a new device
python gitpush.py clone yourname/myscripts
python gitpush.py clone myscripts # your own repos: name alone is enough# Pull changes made elsewhere - by folder or by repo name
python gitpush.py pull ./myscripts
python gitpush.py pull yourname/myscripts # clones automatically if not present

Push ALL your project folders at once - each becomes its own repo

python gitpush.py pushall ~/Documents/projects
python gitpush.py pushall ~/Documents/projects -n # preview first

Everyday workflow

# hack on your scripts...
python gitpush.py push ./myscripts # done. that's the whole workflow.

FAQ / gotchas

"Repo X already exists but your token can't see it" — fine-grained token without that repo under Repository access. Edit the token on GitHub and add it.

GitHub refused to create the repo (401/403/404) — token is missing Administration: write, or is expired.

pull fails on a brand-new repo — the branch must exist on GitHub first. Push once, then pull works.

Where does the token go? — only into memory for the API call and push URL. Never written to disk.

Something's junk-filtered that you actually want — edit SKIP_PARTS / SKIP_NAMES / SKIP_SUFFIXES at the top of gitpush.py.

Works with classic tokens too (ghp_... with repo scope) — everything behaves the same.

About

A dulwich based pure python git interface for a-Shell

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages