linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Chapters
  • How it works
  • Lessons
  • Knowledge base
  • Interview prep
home/git/lessons/git-lab-07-1-atomic-commits

lesson ── git-labs ── ~20 мин ── 7 шагов

Atomic commits: add -p and amend

The goal is to learn how to cut a large set of changes into small, topic-focused commits with git add -p. And to fix a commit you just made without a new entry in history, using git commit --amend.

▶ интерактивный sandbox

Поднимется контейнер gitlab/git-base с git, bash, pre-commit. В браузере откроется терминал, можно сразу git init. Каждый шаг проверяется автоматически. Сеть air-gapped, github.com недоступен.

запустить sandbox →

stack ── git · bash · 256 MB RAM · air-gapped · самоуничтожается через 30 мин простоя

Шаги

  1. 01

    Create a repo and a first meaningful file

    bash
    cd /home/student/work
    mkdir -p atomic-lab && cd atomic-lab
    git init -b main
    cat > server.js <<'EOF'
    function add(a, b) {
      return a + b;
    }
    console.log(add(2, 3));
    EOF
    git add . && git commit -m "init: add function"
    git log --oneline

    The starting point is one file with one function.

    ✓ Starting commit is in place.

  2. 02

    Make three different changes in one file

    Imagine a typical workday: you tweaked the typing, added a new feature, fixed a bug, all in one file.

    bash
    cd /home/student/work/atomic-lab
    cat > server.js <<'EOF'
    // refactor: jsdoc types
    /**
     * @param {number} a
     * @param {number} b
     */
    function add(a, b) {
      if (a == null || b == null) return 0;
      return a + b;
    }
    // feat: subtract
    function sub(a, b) {
      return a - b;
    }
    console.log(add(2, 3));
    console.log(sub(5, 2));
    EOF
    git diff

    Three topics are mixed together: refactor (jsdoc), fix (null-check), feat (sub). In normal work you would just commit this as "misc changes". Now you will split them.

    ✓ Three topics in one diff. Next you will cut them apart.

  3. 03

    First, fix the last commit's message with amend

    Since the file is already changed, practice amend on the message separately. First, make the working tree clean again:

    bash
    cd /home/student/work/atomic-lab
    git stash push -m "wip-mess"  # set uncommitted work aside in the stash with a label
    git log --oneline
    # --amend replaces the last commit with a new one (with a different SHA), -m sets the new message
    git commit --amend -m "init: add function with two-arg signature"
    git log --oneline             # the commit's SHA changed
    git stash pop                 # bring the stashed work back

    Notice: the message changed, but the commit's SHA became a different one (check with git log -1 --format=%H). amend is not an "edit in place"; it creates a new commit and moves the branch pointer.

    ✓ Message fixed with amend. Next, add -p.

  4. 04

    Stage only the refactor part (jsdoc) into the index

    git add -p server.js starts an interactive dialog. For each hunk Git asks: Stage this hunk [y,n,q,a,d,s,e,?]?.

    The most useful answers:

    • y is yes, into the index
    • n is no, leave it in the working tree
    • s is split (cut the hunk into smaller ones)
    • q is quit
    bash
    cd /home/student/work/atomic-lab
    git add -p server.js          # -p (--patch) = interactive staging by hunk

    Answer y on the hunk with the jsdoc types and null-check refactor (use s if they are stuck together), n on everything that touches sub. After that, check:

    bash
    git diff --cached             # what went into the index (ready to commit)
    git diff                      # what is left unstaged in the working tree

    Only the refactor should land in the index. Subtract stayed in the working tree.

    подсказка

    If you get lost in the interactive prompt, `q` exits. The run is non-destructive, so you can repeat it.

    ✓ Refactor in the index, feature still in the working tree.

  5. 05

    Commit the refactor as its own commit

    bash
    cd /home/student/work/atomic-lab
    git commit -m "refactor: add jsdoc types and null-check"
    git log --oneline
    git status

    Status shows that server.js is still modified: subtract is in the working tree.

    ✓ First atomic commit is ready.

  6. 06

    Commit the subtract feature separately

    Now add the rest, which is only feat:

    bash
    cd /home/student/work/atomic-lab
    git add server.js
    git diff --cached
    git commit -m "feat: add sub function"
    git log --oneline

    Three commits: init, refactor, feat. Each one is its own topic.

    ✓ Atomic decomposition is done.

  7. 07

    Add to the last commit with amend

    Noticed you forgot to add console.log(sub(...)) as a separate commit? It is part of the same feature, so you can fold it into an amend.

    But console.log is already in the file. Simulate "forgot and added it":

    bash
    cd /home/student/work/atomic-lab
    echo "// usage example below" > note.txt
    git add note.txt
    # --amend = replace HEAD with a new commit, --no-edit = keep the old message
    git commit --amend --no-edit
    git log --oneline             # the commit count is the same, but HEAD now contains note.txt
    git show HEAD --stat          # --stat = short summary of changed files

    --amend --no-edit added the file to the last commit and kept the message. History is still 3 commits, but the last one now contains note.txt.

    Rule: amend only before you push to a shared branch. On a pushed branch this means a force-push, which breaks git pull for everyone else.

    ✓ Amend added to the commit. History stayed short.

Что ты узнал

git add -p is interactive staging by hunk. You can build a commit from part of the changes in a file. git commit --amend rewrites the last commit: either the message or the content.

команды

  • git add -p fileinteractively pick hunks for staging
  • git diff --cachedcheck what went into the index before the commit
  • git commit --amendfix the last commit (message or content)
  • git commit --amend --no-editkeep the message, add a new stage

концепции

  • · an atomic commit = one logical change
  • · add -p lets you build a commit from part of a file
  • · amend changes the commit's SHA, so do not run it on pushed branches

← предыдущая

Branches: create, switch, merge, delete

следующая →

Merge vs rebase: by hand in one repository

Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies