A Practical Git + GitHub Workflow for Solo Developers
An end-to-end workflow for using Git with GitHub: create a repo, set up SSH, push your code, work with branches and pull requests, and recover from common mistakes.
What you'll learn
- ✓How to create a GitHub repository and connect your local one
- ✓How to set up SSH authentication once and never touch it again
- ✓The daily cycle: pull, branch, commit, push, pull request
- ✓How to clone an existing repository and keep it in sync
- ✓How to recover from the three most common Git mistakes
Prerequisites
- •A working Git install and understanding of branches — see Git Branching
- •A free GitHub account at github.com
This final post in the series stitches the previous four together into a workflow you can actually use every day. The setting is GitHub, because that is what nearly everyone uses, but everything below applies almost identically to GitLab and Bitbucket.
The goal is a routine that is safe (hard to lose work), simple (few commands per day), and professional (the same shape that real teams use). For a solo developer this is overkill on day one and exactly right by month three.
Step 1: Authenticate with SSH (once)
You can talk to GitHub over HTTPS or SSH. HTTPS requires typing a password (or token) for every push; SSH uses a key pair and is invisible after setup. Set up SSH once and forget about it.
Generate a key on your machine:
ssh-keygen -t ed25519 -C "you@example.com"
Accept the default location by pressing Enter. You can leave the passphrase empty for now or set one for extra security.
Copy the public key (the one ending in .pub):
# macOS
cat ~/.ssh/id_ed25519.pub | pbcopy
# Linux (with xclip)
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard
# Windows (Git Bash)
cat ~/.ssh/id_ed25519.pub | clip
On GitHub, go to Settings → SSH and GPG keys → New SSH key, paste the key, and save. Test the connection:
ssh -T git@github.com
You should see a message like Hi yourname! You've successfully authenticated…. From now on, every Git command that talks to GitHub will use this key automatically.
Step 2: Create a repository on GitHub
On GitHub, click the + in the top right and choose New repository. Give it a name, leave it empty (no README, no .gitignore, no licence — you will add those locally), and create it. GitHub will show you a page of setup instructions; you only need a few lines from it.
If you already have a local repository from the install post:
cd ~/code/first-repo
git remote add origin git@github.com:yourname/first-repo.git
git branch -M main
git push -u origin main
Three things just happened:
git remote add origin <url>told your local repo where its “home” on GitHub lives. The nameoriginis just a label — by convention, the primary remote is called that.git branch -M mainrenamed the current branch tomain(harmless if it was already calledmain).git push -u origin mainuploaded all your commits to GitHub and setmainto trackorigin/main— meaning from now on, plaingit pushandgit pullknow which remote branch they refer to.
Refresh the GitHub page and you should see your files.
Step 3: Clone an existing repository
The other direction — starting from a repository that already exists on GitHub — is even simpler:
git clone git@github.com:someone/their-repo.git
cd their-repo
git clone does five things in one: it downloads the entire history, creates a folder, initialises a repo inside it, sets origin to point at the GitHub URL, and checks out the default branch. After cloning you can immediately start working.
The daily cycle
This is the shape of nearly every day on a Git-and-GitHub project. Read it once now, then come back when you forget.
# 1. Sync with the remote before starting
git switch main
git pull
# 2. Create a branch for whatever you are about to do
git switch -c add-search-bar
# 3. Edit, save, stage, commit — as many times as you like
git add .
git commit -m "Add basic search bar markup"
# (more edits, more commits)
# 4. Push the branch to GitHub
git push -u origin add-search-bar
# 5. Open a pull request on github.com
# Review your own diff, merge it into main on GitHub.
# 6. Locally, sync and clean up
git switch main
git pull
git branch -d add-search-bar
Six steps, the same six every day. Once it is in muscle memory, it takes seconds.
A few things worth noticing:
- Always pull before branching. This guarantees your new branch is based on the latest
main, which makes the eventual merge trivial. - Push early, push often. A pushed branch on GitHub is a safe backup. If your laptop is run over by a bus, your work survives.
- Delete branches after merging. GitHub offers to do this for you in the pull request UI. Keep both the local and the remote tidy.
Pull requests, briefly
A pull request (PR) is GitHub’s name for “I would like to merge this branch into another one.” Even when you are working alone, PRs are useful:
- They show you the diff in a clean, line-by-line view.
- They run any automated tests configured for the project.
- They give you a written record of why the change happened.
- They are the universal collaboration format for code on the internet.
To open one: push your branch, then visit your repository on GitHub. A yellow banner offers to open a PR for the branch you just pushed. Click it, write a one-paragraph description, click Create pull request, and then — assuming everything looks good — Merge pull request.
GitHub offers three merge styles: a regular merge, “squash and merge” (combine the branch into a single commit), and “rebase and merge” (replay each commit one by one on top of main). For solo work, squash and merge is a fine default — your main history becomes one line of well-described commits regardless of how messy the branch was.
Pull, fetch, and the difference
Two commands often confused:
git fetchdownloads new commits from the remote but does not touch your branches. Your localmainstays where it is; you can inspect what changed on the remote withgit log main..origin/main.git pullisgit fetchfollowed by either a merge or a rebase into your current branch.
In day-to-day work, git pull on main is what you want. git fetch is for the cases when you want to see what is on the remote before deciding what to do.
Try it yourself. Create a repository on GitHub, follow the setup above, then run the full daily cycle: branch, two commits, push, PR, merge, sync, delete branch. Do it twice. The second time will feel routine.
Recovering from common mistakes
Three situations come up so often that knowing the fixes by heart will save you hours.
”I committed to the wrong branch”
You meant to be on feature and accidentally committed to main. As long as you have not pushed yet:
# On main, with the unwanted commit at the tip
git switch -c feature # create a new branch from current state
git switch main
git reset --hard HEAD~1 # move main back by one commit
The commit now lives on feature and main is clean. If you have already pushed the commit to main, do not reset — use git revert <hash> instead, which records a new commit that undoes the change.
”I want to undo my last commit but keep the changes”
git reset --soft HEAD~1
The commit is gone but its changes are back in the staging area, ready to be edited and re-committed. This is the right move when you realise immediately after committing that the message was wrong or you missed a file.
”I changed a file and want to throw away the change”
The change is in the working tree only — not staged, not committed:
git restore <file>
This rewrites the file back to the version in the last commit. It is destructive — any uncommitted edits to that file are gone for good. Make sure you really want to throw them away. To discard every change in the working tree at once:
git restore .
A safety note about reset --hard and push --force
Two commands can lose work permanently if used carelessly: git reset --hard (rewrites the working tree and discards uncommitted changes) and git push --force (overwrites the remote branch, potentially erasing commits other people have based work on).
Neither is evil. Both are necessary occasionally. The rule is the same as for rebase: never use them on branches other people are working with. On a private branch that only you touch, they are fine.
A few quality-of-life settings
These are entirely optional but every experienced Git user runs them:
# Make pushes safer — only push the current branch by default
git config --global push.default current
# Colour the output of git status, diff, log, etc.
git config --global color.ui auto
# Show branch and ahead/behind info in `git status -sb`
git config --global status.short true
# Useful one-letter aliases
git config --global alias.s "status -sb"
git config --global alias.l "log --oneline --graph --decorate --all"
git config --global alias.co "switch"
git config --global alias.cm "commit -m"
The aliases mean you can type git s, git l, git co main, and git cm "Fix typo". Small, but you do them a thousand times a year.
Try it yourself. Set up the four aliases above. From now on, end every editing session by running git s and git l — the first to see what you have done, the second to see how it fits into the broader history. After a week these become as natural as ls.
Where to go from here
This series has covered the everyday surface of Git: the mental model, the core commands, branches, merge vs. rebase, and a real workflow with GitHub. That is roughly 80% of what you will use in the first five years of a professional career.
The remaining 20% is worth knowing eventually:
- Tags and releases — marking specific commits as versioned releases.
- Stashing (
git stash) — temporarily setting aside uncommitted work. - Cherry-picking (
git cherry-pick <hash>) — copying a single commit from one branch onto another. - Bisecting (
git bisect) — automatically finding the commit that introduced a bug. - Submodules and subtrees — embedding one repository inside another.
- Hooks — running scripts automatically on commit, push, etc.
None of those is needed for normal day-to-day work. Look them up when you encounter a problem that needs them; their documentation is good.
The single best thing you can do to improve at Git is use it for everything — notes, configs, scripts, half-finished side projects. Once branching, committing, and pushing are reflexes rather than ceremonies, the rest of the tool reveals itself naturally.
Recap
You now have:
- An SSH-authenticated link between your machine and GitHub.
- The full daily cycle in muscle memory: pull, branch, commit, push, PR, sync.
- The vocabulary to talk about remotes, pull requests, and tracking branches.
- A small kit of recovery moves for the most common Git accidents.
- A few quality-of-life settings and aliases that smooth out everyday work.
That is more than enough to contribute to open source, collaborate on a team, or run your own projects with the same discipline professional teams use.
Next steps
This is the final post in the Git beginner series. The natural next move is to use it on a real project — fork an open-source repository on GitHub that interests you, clone it, make a small fix, and open a pull request. There is no faster way to consolidate everything in this series.
Questions or feedback? Email codeloomdevv@gmail.com.