Skip to content

Commits ​

A good commit holds one logical change and says why it was made. This lesson shows how to choose exactly what goes into a commit, check it before you save it, fix the last one, keep junk out, and make sure it carries the right name.

The examples continue the trip-planner repository from lesson 1, with a twelve-line packing.txt.

See what you changed: git diff ​

You make two unrelated edits to packing.txt: you change Tickets to Train tickets near the top, and add Sunglasses at the bottom. git diff shows what changed in the working tree compared with the staging area:

bash
git diff
text
diff --git a/packing.txt b/packing.txt
index 07ec381..6aba0a6 100644
--- a/packing.txt
+++ b/packing.txt
@@ -1,5 +1,5 @@
 Passport
-Tickets
+Train tickets
 Phone charger
 Toothbrush
 Rain jacket
@@ -10,3 +10,4 @@ Water bottle
 Snacks
 Book
 Headphones
+Sunglasses

How to read it:

  • Lines starting with - were removed, lines starting with + were added. A changed line shows as one removal and one addition.
  • Lines starting with a space are unchanged context, shown so you can see where the change is.
  • Each @@ … @@ line starts a hunk: one block of nearby changes. -1,5 +1,5 means "lines 1 to 5 before, lines 1 to 5 after".

This diff has two hunks, because the two edits are far apart.

CommandCompares
git diffWorking tree with the staging area: what you have not staged yet
git diff --stagedStaging area with the last commit: what will be committed
git diff HEADWorking tree with the last commit: everything since then

--cached is another name for --staged.

Stage part of a file ​

The two edits are two different changes, so they belong in two commits. You can stage one hunk and leave the other.

In a terminal, git add -p (for "patch") walks through each hunk and asks:

bash
git add -p
text
@@ -1,5 +1,5 @@
 Passport
-Tickets
+Train tickets
 Phone charger
 Toothbrush
 Rain jacket
(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,P,?]? y
@@ -10,3 +10,4 @@ Water bottle
 Snacks
 Book
 Headphones
+Sunglasses
(2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,P,?]? n

y stages the hunk, n skips it, q stops, ? explains every letter. Now the same file is both staged and not staged:

bash
git status --short
text
MM packing.txt

Check exactly what will be committed:

bash
git diff --staged
text
…
@@ -1,5 +1,5 @@
 Passport
-Tickets
+Train tickets
 Phone charger
…

Only the tickets change. Commit it, then stage and commit the rest:

bash
git commit -m "Say which tickets to pack"
git add packing.txt
git commit -m "Add sunglases to packing list"
text
[main f11adbc] Say which tickets to pack
 1 file changed, 1 insertion(+), 1 deletion(-)
[main 77774ef] Add sunglases to packing list
 1 file changed, 1 insertion(+)

In BranchPilot, select the file under Unstaged to see its diff, then select Stage hunk on the hunk you want. The file then appears under both Staged and Unstaged, the same as MM above.

TIP

Read git diff --staged (or the Staged view in BranchPilot) before every commit. It is the cheapest way to catch a stray debug line, a password or a file you did not mean to include.

Fix the last commit: amend ​

The second message has a typo. --amend replaces the most recent commit with a corrected one:

bash
git commit --amend -m "Add sunglasses to packing list"
git log --oneline -2
text
719f474 Add sunglasses to packing list
f11adbc Say which tickets to pack

The commit has a new hash, 719f474 instead of 77774ef: amending makes a new commit and drops the old one from the branch. To add a forgotten file instead, stage it and run git commit --amend --no-edit to keep the message.

In BranchPilot, turn on Amend in the commit box. See Amend the last commit.

WARNING

Only amend commits you have not pushed. Once other people have the old commit, replacing it causes trouble for them. Lesson 4 explains why.

Write messages people can use ​

In six months, the message is the only explanation anyone has. A widely used convention:

text
Add sunglasses to packing list           ← subject: what, in about 50 characters

The forecast says 30 degrees on Saturday ← blank line, then the body: why
and we will be outside most of the day.
  • Subject: one line, ideally 50 characters or fewer, never more than 72. No full stop at the end.
  • Write it as a command: "Add", "Fix", "Remove", not "Added" or "Adding". Read it as "This commit will… add sunglasses to packing list."
  • Body (optional): after a blank line, explain why the change was needed. The diff already shows what changed.
  • One logical change per commit. "Fix login bug and rename variables and update logo" is three commits.
WeakBetter
fixFix crash when the packing list is empty
changesSay which tickets to pack
WIPAdd draft day plan for Saturday

To write a body, run git commit without -m. Git opens your text editor; write the subject, a blank line and the body, then save and close. In BranchPilot, use Commit subject and Description (optional); the counter turns amber past 50 characters and red past 72.

Keep files out: .gitignore ​

Some files should never be committed: settings with passwords, logs, build output, editor junk. A file called .gitignore at the top of the repository lists patterns Git should ignore.

bash
git status --short
text
?? .env
?? build/
?? debug.log

Create .gitignore with:

text
.env
*.log
build/

Now Git stops offering those files:

bash
git status --short
text
?? .gitignore

Commit .gitignore itself, so everyone who works on the project gets the same rules.

PatternIgnores
.envAny file or folder called .env
*.logEvery file ending in .log
build/Any folder called build, with everything in it
/notes.txtnotes.txt at the top of the repository only
!keep.logUn-ignores keep.log, even though *.log matched it

To find out why a file is ignored, ask Git:

bash
git check-ignore -v debug.log
text
.gitignore:2:*.log	debug.log

.gitignore does not untrack

Ignoring only affects files Git is not already tracking. If .env was committed before you added the rule, Git keeps tracking it. Stop tracking it with git rm --cached .env (the file stays on disk) and commit. The old commits still contain it, which matters a lot if it held a password: see Stay safe.

Your identity: name and email ​

Every commit records an author name and email from two settings:

bash
git config --global user.name "Asha Rao"
git config --global user.email "asha@example.com"

--global saves them in your user settings file (~/.gitconfig) for every repository. Without --global, run inside a repository, they apply to that repository only and override the global ones. To see which value wins and where it comes from:

bash
git config --show-origin user.email
text
file:.git/config	asha.rao@work.example

If Git has no identity at all, the commit stops:

text
Author identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

Why the wrong identity matters ​

The name and email are not a sign-in; Git does not check them. But hosting sites use the email to link each commit to an account, and the history is permanent once shared. Common accidents:

  • Work commits under your personal email. Your private address is now in your employer's history, and the commits may not count as yours on the work account.
  • Personal or open-source commits under your work email. Your employer's address appears in public projects.
  • A placeholder identity like root@localhost that links to nobody.

Fixing an identity after a push means rewriting history, so it is far better to get it right first. Two habits help:

  • Before your first commit in a new repository, run git config user.email and check the answer.
  • If you do not want your email public, hosting sites such as GitHub offer a private "noreply" address you can use as user.email.

If you work as more than one person, for example work and personal accounts on Windows, DhivaLabs Shell gives each identity its own commit name and email, SSH key and history, and its guard blocks a commit or push when the repository belongs to another identity. See Commit identity and the Git guard.

To fix the author of the last commit, before you push: set the right identity, then run git commit --amend --reset-author --no-edit.

Check yourself ​

QuizCommits

Question 1 of 6

You fixed a bug at the top of a file and left a debug line at the bottom. How do you commit only the fix?

Score: 0

What you learned ​

  • git diff shows unstaged changes; git diff --staged shows what the next commit will contain.
  • A hunk is one block of nearby changes; git add -p or BranchPilot's Stage hunk stages one at a time.
  • A good commit is one logical change with a short subject in the command form and a body that says why.
  • git commit --amend replaces the last commit; do it only before you push.
  • .gitignore keeps untracked files out, but does not untrack files already committed.
  • user.name and user.email go into every commit; check them before you commit in a new repository.

Next steps ​