Git and GitHub, from the beginning
Git is a program on your own computer that, whenever you tell it to, keeps a dated snapshot of your project along with a note, and later lets you return to any of those snapshots. GitHub is one of the places you can keep a copy of that history; git itself works perfectly with no internet and no account.
- Lesson 9 of 14
- Beginner
- Free, no signup
The life of one change, from edit to history
-
1
Edit the file
Git has done nothing yet. The change is on disk and not in the history.
-
2
git add
You choose what goes into this snapshot. This is the step that usually gets forgotten.
-
3
git commit
The snapshot is recorded with a date, a name and a message. From here it is recoverable.
-
4
git push
A copy of the history also lands on a host. The only step that needs a network.
-
5
git log
Every snapshot comes back with its date and message. Here you learn what a good message was worth.
This order is for one person on one branch. Teamwork adds pull, merge and conflict resolution, which this lesson does not cover.
Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.
What does git solve that copying the folder does not?
Everyone has seen the pre-git method: site, site-final, site-final-2, and that one folder nobody dares delete. The problem with it is not that it is ugly; it is that none of those folders says why it was made or which files changed together.
Git is a version control system: instead of holding several complete copies, it records the state of the project at points you choose. Each point is a commit, and it carries three things a copied folder never has: an exact date and time, the name of whoever recorded it, and a message saying why the change was made.
That third thing is where git's real value sits. Six months later, when you reach a line whose meaning escapes you, your question is not where the line came from; it is why somebody did that. Git answers exactly that question, provided you wrote the messages seriously. A history full of "changes" and "fix" is precisely as useless as the final-2 folder.
And one practical difference that helps you sooner than the rest: git lets you see exactly which lines differ between two points. When a site that worked yesterday is broken today, that is not a convenience feature, it is the only way to find the cause in minutes instead of hours.
Git and GitHub are not the same thing
Git is a program installed on your own computer whose job is keeping history. GitHub is a company that hosts those histories on its servers and has built other things around them: profile pages, issue tracking, code review and the rest. One is a tool, the other a service; roughly what Word is to email.
That distinction carries a property tutorials usually lose: git is distributed, meaning your computer holds a complete copy of the history rather than a pointer to a server. You can commit all day, read the history and go back in time without connecting to the internet once. push only puts a copy of that same history somewhere else as well.
So if that host becomes unreachable tomorrow, the repository on your machine does not become partial, and you can send it anywhere else: GitLab, a private server, even an external drive. What is lost with the host is the issues, the pull requests and the discussions under them, because those are not inside git at all and are the company's own product.
One practical sentence for the reader in Iran: whether foreign hosting services are reachable is something to test yourself on the day, and we do not write today's claim about it here. The right decision is independent of that anyway: keep the history somewhere that does not stop your work if one service goes away. That fits what git already is and depends on no service.
Where does the history live? On both computers
Your computer
- A complete copy of the history, not a pointer
- Committing works with no internet
A teammate's computer
- They hold the same complete history
- Each of you works independently, then syncs
The host is only a copy, not the owner of the history
GitHub or any other host
- A shared copy in the middle, for syncing
- Issues, code review and profiles are its own additions
If the host becomes unreachable, the code history is intact and can be pushed anywhere else. What goes with the host is the issues and code reviews, because those are not inside git.
The first four commands, and what add is even for
You put a project under git with git init. That command creates a hidden folder called .git, and from then on anything happening in that folder can be recorded. Nothing has been recorded yet; the ledger has merely been opened.
git init
git add index.html
git commit -m "first page with contact form"
git push origin mainThe command that confuses beginners is add, because it looks like a needless extra step. It is not. Between your files and the history sits a middle table called the staging area, and add means "put this on the table, I want it in the next snapshot". That table is what lets you record only the three files belonging to one job, out of the ten you changed today, in a single commit.
This is where the first professional habit forms: one commit should be one job. If you have to use the word "and" in the commit message, it should probably be two commits. This is not a matter of taste; you pay for it on the day you want to undo one change and that change is mixed into a commit with two other jobs.
And push is the only one of the four that needs a network. The first three work entirely on your own machine. Keep that in mind and git's error messages start making sense: an access or authentication error is almost always about push, and "nothing to commit" almost always means you forgot add.
The first thing that goes wrong: a file that should never have been committed
A file called .gitignore at the root of the project tells git what to leave alone. Three categories are always in it: the dependency folder that can be reinstalled, files produced by a build, and anything holding a real password or key.
The third category is where people get hurt. A settings file with the database password gets committed once, then somebody notices, removes the password from the file and makes a new commit. The job is not done: git keeps history, and that password still sits inside the earlier commit, visible with one simple command.
GitHub's own guide says the same: after something like that you must treat the credential as compromised and change it, and removing the file from history is not enough on its own. The correct order is also the reverse of what people expect: rotate the password first, then think about cleaning the history.
So the habit worth having from day one is this: write .gitignore before the first commit, not after it. And if the project needs a settings sample, ship a file like config.example with empty values, so the next person knows what is required without any real value being recorded anywhere.
Commit these
- The project's own code and text files
- The dependency lock file, so everyone installs one version
- A settings sample with empty values
- The gitignore file itself
Never commit these
- A settings file with a real password or key
- The dependency folder that one command reinstalls
- Build output and generated files
- Database backups and user uploads
This file only stops what has not been committed yet. A file already committed is not removed from history by adding it to this list.
The site this lesson was written on is not in git
rgb.ir is edited on a live server and has no git repository. We write that down because a lesson that only advises, without saying where it stands itself, is half the truth.
So what took git's place? The editor we wrote for the theme puts a copy of the file aside before every save, named by date and time, and keeps the last twenty versions of each file. It then parses the new file with token_get_all and the TOKEN_PARSE flag, because both php -l and proc_open are disabled on this server and the usual syntax check is unavailable. If the new file does not parse, that earlier copy is restored automatically so the live page does not go down.
That is roughly the minimum definition of a version system, and it does its job well. But its difference from git is exactly what this lesson has been about: none of those twenty copies says why it was saved, nothing links two files that changed together, and past the twenty first version nothing remains.
So if your project is not in git yet, this lesson is not a scolding. Just know the cost: not having git costs nothing at all on the day everything works, and collects the entire bill on the day it does not.
The fast path, with AI
What professionals do with AI and git in 2026 is not giving a model permission to run commands; it is the opposite. You show it the changes about to be recorded and, before committing, ask for three things: have I mixed unrelated jobs together, is there anything resembling a secret in here, and a commit message that says why rather than what. The second item is what separates this recipe from an ordinary commit-message request, and it is where most of the value sits.
- Use <code>git add -p</code> to pick what goes on the table hunk by hunk, rather than adding the whole folder. That one command removes half the mistakes in this job before they happen.
- Take the output of <code>git diff --staged</code> and send it with the recipe below. Read the answers to items one and two first, then go to the message.
- If anything resembling a key or password is listed, stop right there: take it off the table with <code>git restore --staged</code>, put the file in gitignore, and if the value was real, change it.
- Take the message from the model's draft but rewrite it yourself. The model reads what changed from the diff, but only you know why, and why is the part that helps six months later.
Copy-ready recipe
This is the output of git diff --staged.
{diff output}
Give me three things, in this order:
1. If these changes contain more than one unrelated job, say which lines belong to which job and propose how to split them into separate commits.
2. List anything resembling a password, key, token, internal address or real customer data. If there is none, say so explicitly.
3. Write a commit message: a first line of at most fifty characters in the imperative, then a blank line, then two to four lines explaining why rather than what.
Do not write any git command for me to run. If answering needs code that is not in this diff, say which and why; do not guess.
Before you trust the output: Two boundaries this recipe does not cross. First, the model only sees that diff: if your change breaks something elsewhere in the project, no trace of it appears in this output and the only way to know is running the program. Second, sending a diff means sending your code to another company; if the project belongs to a client, have their permission first and read that service's own data-use page. The last line of the recipe is not decoration either: a git command you cannot explain does not get run.
AI in this kind of work
Our position on git and AI is plain: keep the model in the role of reading and writing text, not of operating your repository. Drafting a commit message, summarising a long diff, and explaining what an old commit did are three things models genuinely do well and that give you time back. Running commands is a different matter, and the risk section says why.
Tools that actually help
- Claude Code It sits in the terminal next to the repository, so instead of copying a diff by hand it reads it itself. For "what did this commit do" and "why is this line here" it is the best option on this list. It installs free but does not run without a Claude subscription or an Anthropic Console account, and Iran is not on Anthropic's supported-countries list.
- Claude For the recipe above, a chat window is enough: you paste the diff and get the three items. Iran is on neither of Anthropic's two supported-countries lists; we read that on Anthropic's own page rather than measuring it.
- Gemini For a commit message and for summarising a diff, a fast cheap model is enough and this is where it belongs; for spotting that two unrelated jobs got mixed, a stronger model answers better. Google's own page says the Gemini web app runs in over 230 countries and territories, and Iran is not on that list.
Where it backfires
The main risk here is one specific class of commands, not the tools. Most git operations are reversible, but three are not, and models suggest exactly those three with complete confidence: git reset --hard, which per git's own documentation throws away uncommitted changes in the working tree; git clean -fd, which deletes untracked files; and git push --force, which replaces the branch on the server with your version and can erase someone else's work. The rule is simple: a command you cannot explain does not get run, and before any of those three, take a git status.
The second risk belongs to pasting rather than running: every diff or file you put in a chat has left your machine, and what happens to it depends on that service's plan and settings and is written on its own data-use page. For a personal project this is a non-issue; for a client's code you need permission first. For how each of these tools can be paid for from Iran see the buying guide, and for our current pick among coding models, the best AI for coding.
Sources: git-scm: git reset git-scm: git clean git-scm: git push, the force option Anthropic: supported countries Google: where the Gemini web app is available
Where this advice stops
This lesson covers one person on one branch. Everything teamwork adds is left out and each piece wants its own lesson: branching, merges and conflicts, rebase, code review and pull requests, and large files, which git was not built for. There is a larger boundary that gets said less often: git is built for text files, and if the thing that changes in your project lives in a database rather than in files, git does not see it. A WordPress site is exactly that shape, which is also why having git for the theme does not by itself count as a backup of the site.
From our own work
This very site has no git repository and is edited on a live server. What took its place is our own template editor plugin: before every save it puts a copy of the file aside, named by date and time plus six random characters, keeps the last twenty versions of each file and deletes older ones, and holds an audit log capped at two hundred rows. After writing, it parses the new file with token_get_all and the TOKEN_PARSE flag, because both php -l and proc_open are disabled on this server; and if it does not parse, that earlier copy is restored automatically. This is close to the minimum of what gets called a version system, and its distance from git is exactly three things: a message saying why, a link between two files that changed together, and a history not capped at twenty versions.
Real follow-up questions
Do I need git for a one person project?
Yes, though not for the reason usually given. The reason is not backup, since there are simpler ways to back things up; the reason is that six months later you are the only person who has to work out why a line was written. Git is what keeps the answer to that question.
What is the difference between git pull and git fetch?
fetch brings the server's changes without touching your work, so you can look at them first. pull does the same and immediately merges them into your branch. When you are unsure, fetch first.
I wrote the commit message wrong, can I change it?
If you have not pushed yet, git commit --amend changes the last commit's message and you are done. If you have pushed, doing this rewrites history and causes trouble for anyone who already pulled that branch; in a shared repository it is better to leave the wrong message alone.