Git workflow for beginners: init, commit, branch, merge, push and undo
AdvertisementGit records the history of a project as a series of commits, and lets several lines of work (branches) grow side by side and then come back together. Most of the confusion beginners feel comes from not seeing the whole loop at once: make a change, save it as a commit, do the work on a branch, merge it, send it to a shared copy, and undo it if it was a mistake. This post walks through that loop once, end to end, with the real output of each command.
How this was tested. I ran every command below with Git 2.55 on a new folder, using a second "bare" folder as the remote (the stand-in for GitHub or GitLab), so no account is needed to follow along. Your hashes (the seven-character codes such as e53ae4f) and dates will differ.
The picture to keep in your head
Git works with three places on your computer, plus the remote:
- Working folder: the files you edit.
- Staging area (the index): the changes you have chosen to include in the next commit.
- Repository (
.git): the commits saved so far. - Remote: another copy of the repository, usually on GitHub, GitLab or Bitbucket, that your team shares.
The commands move changes between those places: git add moves from the folder to the staging area, git commit moves from the staging area to the repository, and git push sends the repository's commits to the remote.
Step 1: Create a repository
git init -b main shop
cd shop
git init creates the hidden .git folder that holds the history. The -b main option names the first branch main, which is the usual name today (older tutorials say master). Next, create a file and ask Git what it sees:
echo "# Shop" > README.md
git status --short
?? README.md
The ?? means the file is untracked: it exists in the folder, but Git is not recording it yet. Use git status constantly; it tells you where you are and what to do next.
Step 2: Add and commit
git add .
git commit -m "Initial commit"
[main (root-commit) e53ae4f] Initial commit
1 file changed, 1 insertion(+)
create mode 100644 README.md
git add . stages every change in the folder. To stage only one file, name it (git add README.md). The commit message should say what changed and why in one short line: "Add cart page" is useful, "changes" is not. The first commit of a repository is shown as the root-commit.
Two habits worth building: commit small, related changes together, and never put passwords, API keys or a production .env file in a commit. A file listed in .gitignore is skipped by git add, so put such files there before your first commit.
Step 3: Connect to a remote and push
git remote add origin ../remote.git
git push -u origin main
To ../remote.git
* [new branch] main -> main
branch 'main' set up to track 'origin/main'.
For a real project, git remote add origin takes the URL that GitHub or GitLab shows when you create an empty repository. The name origin is only a conventional nickname for that remote. The -u option links your local main with origin/main, so from now on a plain git push or git pull knows where to go.
Step 4: Work on a branch
Never build a new feature straight on main. A branch is a separate line of commits, so main stays working while you experiment:
git switch -c feature/cart
echo "cart" > cart.txt
git add cart.txt
git commit -m "Add cart"
git log --oneline --graph --all
Switched to a new branch 'feature/cart'
* 1f76d30 Add cart
* e53ae4f Initial commit
git switch -c name creates a branch and moves to it. (Older tutorials use git checkout -b name, which does the same thing; git switch is the newer, clearer command.) To go back, run git switch main. Your files change to match the branch you switched to.
Step 5: Merge it back
Meanwhile somebody changed main. That is normal on a team:
git switch main
echo "line from main" >> README.md
git commit -am "Update readme on main"
git merge feature/cart -m "Merge cart"
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
Merge made by the 'ort' strategy.
cart.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 cart.txt
Because both branches had new commits, Git created a merge commit that joins them. git log --oneline --graph --all draws the shape, with a fork where the branches split and a join where they met:
* a99ce53 Merge cart
|\
| * 1f76d30 Add cart
* | 2aa8041 Update readme on main
|/
* e53ae4f Initial commit
If main had not changed, Git would simply move the main label forward (a "fast-forward") and make no merge commit. Once a branch is merged you can delete it with git branch -d feature/cart; Git refuses to delete a branch that has unmerged work, which is a useful safety net.
Step 6: Resolve a merge conflict
A conflict happens when two branches change the same lines, so Git cannot choose. Here two branches each created note.txt with different text:
git merge fix-b
Auto-merging note.txt
CONFLICT (add/add): Merge conflict in note.txt
Automatic merge failed; fix conflicts and then commit the result.
Git stopped halfway and marked the file:
<<<<<<< HEAD
A version
=======
B version
>>>>>>> fix-b
Everything between <<<<<<< HEAD and ======= is your current branch's version; the part down to >>>>>>> fix-b comes from the branch you are merging. To resolve it:
- Open the file and decide what the final text should be (one side, the other, or a mix).
- Delete the three marker lines (
<<<<<<<,=======,>>>>>>>). - Run
git add note.txt, thengit committo finish the merge.
If you panic, git merge --abort returns everything to the state before the merge began. In my run, git status --short showed AA note.txt during the conflict ("both added"), and after --abort it printed nothing: the folder was clean again.
Step 7: Undo a mistake
What you do depends on whether the commit has already been shared.
- Not pushed yet: you can still change your own history, for example by amending the last message with
git commit --amend. - Already pushed: do not rewrite history, because teammates may have built on it. Use
git revert, which adds a new commit that undoes an old one:
git revert --no-edit HEAD
git log --oneline
[main 2c0c4b5] Revert "note A"
Date: Sat Oct 24 16:10:35 2026 +0530
1 file changed, 1 deletion(-)
2c0c4b5 Revert "note A"
40255f3 note A
a99ce53 Merge cart
The bad commit stays in the history and the revert cancels it, so the history stays honest and anyone who pulls simply receives one more commit.
To look at an older version without changing anything, find its hash with git log --oneline and run git switch --detach <hash>; return with git switch main. Do not make commits in that detached state unless you create a branch first.
A simple daily routine
git switch mainandgit pullto get the latest work.git switch -c feature/short-namefor each task.- Edit, then
git status,git addandgit commitin small steps. git push -u origin feature/short-nameto publish the branch, then open a pull request (or merge locally if you work alone).- After the merge, switch back to
main, pull, and delete the finished branch.
If you deploy the code to a server, the same repository can feed a release: see deploying code from Git to cPanel hosting for a production branch and rollback.
Common mistakes
- Committing secrets such as
.envfiles. Add them to.gitignorefirst; if one is already committed, change the password, since deleting the file does not remove it from history. - Working on
maindirectly and then mixing unfinished work with a hot fix. - Vague messages like "update" or "fix", which make
git loguseless later. - Resolving a conflict by deleting the markers only, leaving duplicated or broken code. Read the result and run the project before committing.
- Rewriting shared history (
git push --force) after others have pulled it. Usegit revertinstead. - Not running
git statusbefore committing, and so staging files you did not mean to include.
Practice
- Create a new folder, run
git init -b main, and make three commits with different messages. View them withgit log --oneline. - Create a branch, change a file on it, change the same line on
main, and merge to cause a conflict. Resolve it by hand. - Create an empty repository on GitHub or GitLab, add it as
originand push. - Make a bad commit, then undo it with
git revertand read the log.