CogniSkill · Git and GitHub for Scripts and Projects

Content review copy. This does not replace the site theme. For SC-300, this preview shows additions; the existing teaching is retained on import.

Take a deliberately flawed capacity classifier from a documented failing baseline to a reviewable repair. Learn what Git actually records, preserve unrelated edits, collaborate through a local remote, resolve a scope conflict and recover using new commits. Your final deliverable is a change another operator can inspect and reproduce—not just a repository with a green badge.

Use Git 2.23 or later, Python 3.10 or later and a new local practice directory. The validated environment uses Git 2.51.1 on Linux. Commands use a Bash-style terminal; PowerShell path syntax and some setup commands differ. No real infrastructure, token or GitHub account is required. The offline bare-remote exercise practices Git transport; GitHub account authentication, permissions and branch protections require separate service-specific verification.

You should be comfortable editing a text file and running a Python unittest command. Python Foundations is helpful, but the five-line classifier is explained below. Do not perform recovery experiments in your CogniSkill source, work repository or any directory containing uncommitted real work.

Four chapters, with practical work

  1. Distinguish your files, the staged snapshot and history
  2. Repair on a branch and commit what you actually reviewed
  3. Collaborate, inspect incoming work and resolve a real conflict
  4. Recover safely and defend the complete change

Applied capability and learning route

Review a narrowly scoped behavioral change with regression evidence.

Follow the lessons in order: establish the model, trace the supplied evidence, attempt the case, compare the worked solution, and complete the changed-condition project. The target is intermediate reasoning within this stated scope, not mastery of the entire profession or product. If a prerequisite is unfamiliar, pause and use the linked foundational teaching before attempting the project.

All teaching, explained answers and core synthetic practice are free. Some operational labs require separately available software, a licensed test tenant or an authorized lab; offline completion does not claim hands-on product proficiency.

How to complete this course

Study the worked examples, attempt the exercises before opening solutions, and submit your own project notes. Completion records are self-reported; practical competence requires the stated verification.

Distinguish your files, the staged snapshot and history

Three places can contain three versions

The working tree is what your editor sees. The index, often called the staging area, holds the snapshot proposed for the next commit. A commit records that snapshot with metadata and parent history. Editing a file after staging it does not silently update the staged version. This distinction lets you organize a reviewable change, but it also lets you accidentally commit an older edit than the one you just tested.

git diff compares unstaged working-tree changes with the index. git diff --cached compares staged changes with the current commit. git status --short summarizes both. In a two-character status such as MM capacity.py, the first column describes an index change and the second a working-tree change. Do not read that as one generic “modified” flag; there are two snapshots to inspect.

Git tracks file contents and paths; it is not a live record of every keystroke, every environmental dependency or every untracked file. A commit of a script does not include your interpreter installation, cloud permissions, private data or unsaved editor buffer. A useful project also records its runtime requirements, fixture, tests and execution limits.

Initialize only the new exercise directory

Copy the downloaded fixture into a new directory named script-project. Open a terminal in that directory and verify its path before initializing. These commands affect this repository only:

git init -b main
git config user.name 'Course Learner'
git config user.email 'learner@example.invalid'
git status --short

The local identity is fictional and is set without --global. It labels the practice commits; it does not authenticate a remote service. If git init -b is unavailable on your older Git, initialize and rename the initial branch explicitly, or use a current supported Git version. The course expects the branch to be named main rather than depending on a machine's global default.

Create .gitignore with these four lines:

__pycache__/
*.pyc
reports/
.env

Ignored patterns guide handling of untracked files. They are not access controls, encryption or a promise that secrets never entered history. A file already tracked remains tracked even if a new pattern matches it. Verify what is staged before committing; do not assume an ignore file retroactively sanitized the repository.

A small program with one known defect

The requirement is exact: accept only integer percentages from 0 through 100, rejecting booleans and other types. Return REVIEW only when free percentage is below 10; exactly 10 returns OK. OK is a rule result, not proof that a device is healthy.

The starting fixture is intentionally wrong:

"""Deliberately flawed starting fixture: repair the exactly-10 boundary."""
def classify_free(percent):
    if type(percent) is not int or not 0 <= percent <= 100:
        raise ValueError('free percent must be an integer from 0 to 100')
    return 'REVIEW' if percent <= 10 else 'OK'

The <= in the return expression includes exactly 10. The validation line's <= 100 is correct and must not be changed. This distinction will matter when you repair the defect. A global search-and-replace for <= 10 can also match the beginning of <= 100 and accidentally reject the valid upper endpoint.

Run the tests below before modifying code. Five tests run; exactly the boundary test should fail. A different failure means your environment or fixture differs from the expected baseline. Investigate it before continuing. Do not change the expected value to make the known defect appear correct.

import unittest
from capacity import classify_free

class CapacityTests(unittest.TestCase):
    def test_below_boundary(self):
        self.assertEqual(classify_free(9),'REVIEW')
    def test_exact_boundary(self):
        self.assertEqual(classify_free(10),'OK')
    def test_above_boundary(self):
        self.assertEqual(classify_free(11),'OK')
    def test_endpoints(self):
        self.assertEqual(classify_free(0),'REVIEW')
        self.assertEqual(classify_free(100),'OK')
    def test_invalid_values(self):
        for value in [-1,101,True,'10',10.0,None]:
            with self.subTest(value=value), self.assertRaises(ValueError):
                classify_free(value)

if __name__ == '__main__':
    unittest.main()

Record a truthful baseline

python -m unittest -v
git add -- capacity.py test_capacity.py README.md .gitignore
git diff --cached
git diff --cached --check
git commit -m 'Add fixture with documented boundary defect'
git log --oneline -3

The test command fails intentionally at this stage; read its output rather than chaining commands under a rule that requires every line to succeed. The commit message discloses the defect. A known-failing exercise baseline is acceptable in this isolated teaching repository; it is not a recommendation to merge known defects into a protected production release.

git diff --cached --check checks certain whitespace problems; it does not run tests or certify functionality. A clean result is useful but narrower than the word “check” might suggest. Keep syntax, style, behavior, authorization and operational review as distinct evidence.

Exercise: inspect before broad staging

Create an untracked scratch-note.txt with a harmless local note and leave it out of the commit. Compare git status --short with the staged file list. Explain why git add . would have a wider scope than the explicit path list.

Worked reasoning

The note appears as untracked but is absent from the index. The next commit only includes the staged paths. Broad staging can include unrelated notes, test outputs or credentials, subject to ignore patterns. Explicit paths reduce accidental scope; they still require content review and do not make a secret-containing chosen file safe.

Reasoning model

A useful change set links a requirement, a failing test, a minimal code change and a passing verification. A green test suite only supports behavior covered by its tests. Review the diff for unrelated edits and secrets, not just the final output. Version control preserves history but does not make committed credentials safe; treat accidental credential exposure through the organization’s incident/rotation process.

Official reference for further study

Repair on a branch and commit what you actually reviewed

A branch names a line of work, not a separate backup drive

A branch is a movable reference in repository history. Switching branches changes the checked-out tracked content when Git can do so safely. Untracked and some uncommitted changes can remain across switches; branch creation alone does not package them into a backup. Inspect status and preserve real work before switching.

Create the repair branch:

git switch -c fix/capacity-boundary
git status --short

In your editor, change only the return expression from percent <= 10 to percent < 10. Leave the validation rule unchanged. Run python -m unittest -v: all five tests should pass. Review git diff -- capacity.py. The behavioral repair is a one-character operator change with meaningful consequences at a requirement boundary.

Small diffs can be high impact. A review should explain why the change is correct, not infer safety from its size. The three neighboring inputs—9, 10 and 11—separate the strict rule from the inclusive defect. The endpoint and invalid-type tests help catch unintended changes elsewhere.

Demonstrate a staged snapshot

git add -- capacity.py
git show :capacity.py
git diff --cached -- capacity.py

Now add the harmless comment # Unstaged local review note. at the end of the working file using your editor. Do not stage it yet. Compare:

git status --short
git diff -- capacity.py
git diff --cached -- capacity.py

Expect MM capacity.py. The cached diff contains the operator repair but not the later comment; the unstaged diff contains the comment. If you committed immediately, the repair would be committed but the comment would remain outside that commit. This is intentional Git behavior, not lost data.

Unstage without erasing the working edit

git restore --staged -- capacity.py
git status --short

The working repair and comment remain, but the index no longer proposes those changes. This is not the same as git restore -- capacity.py, which can overwrite working-tree content. Do not run worktree-discarding variants casually. Ask which location you intend to change, what is recoverable and whether the file contains someone else's uncommitted work.

For this exercise, keep the harmless comment, stage the full intended change again, inspect it and test it:

git add -- capacity.py
git diff --cached -- capacity.py
git diff --cached --check
python -m unittest -v
git commit -m 'Fix strict below-10 capacity boundary'
git status --short

The untracked scratch note may still appear. That is fine if deliberately excluded; explain it. A clean tracked diff does not mean every file in the directory was committed. To verify exactly what a colleague receives, use an independent clone later rather than relying only on your working directory.

Write the change review before merging

Prepare a short review brief: requirement, observed failure, change, independent tests, unchanged behavior and limits. For this repair, record 9→REVIEW, 10→OK, 11→OK, valid endpoints and rejected non-integer/out-of-range values. Mention that no collection adapter, device health check or live infrastructure integration was added.

Do not attach real inventory, passwords or environment files to a public issue. A reviewable synthetic fixture can demonstrate the defect without revealing an organization's data. If a secret has already been published, involve the appropriate owner and revoke or rotate it; deleting the visible line is not proof that old copies disappeared.

Bring the reviewed repair into main

git switch main
git merge --ff-only fix/capacity-boundary
python -m unittest -v
git log --oneline -4

With the exercise's unchanged main history, the merge fast-forwards. --ff-only refuses a divergent situation instead of silently creating a merge you have not reviewed. If it refuses, inspect the histories and decide on a deliberate merge or other approved workflow. Do not use a force operation merely to reproduce the screenshot or command transcript.

Evidence laboratory — attempt before reading the solution

Requirement: alert below 10% free space, not at exactly 10%. Current function returns Alert when percent <= 10. Existing tests cover 9 and 11 only. A proposed patch changes <= to <, but also renames an unrelated configuration key. Before editing, write the missing regression test, predict its result on the old code and define the desired diff.

Official reference for further study

Collaborate, inspect incoming work and resolve a real conflict

Practice transport without publishing externally

Run the following from script-project. The sibling destinations must be new. A bare repository holds Git history without a normal checked-out project tree. It can serve as a local remote for this exercise:

git init --bare ../team.git
git remote add origin ../team.git
git push -u origin main
git clone --branch main ../team.git ../peer

The remote name origin is a convention, not a trusted authority. A real remote may have another name or URL. Inspect git remote -v before pushing and ensure that the destination and repository visibility are authorized. These commands publish only to a local path in the isolated lab.

From the peer directory, run the tests. The repaired behavior should pass independently. This clone receives committed files, not your excluded scratch note or an unstaged repair. If the original directory passed tests only because of an uncommitted change, the clone reveals that mismatch.

Make a peer documentation change

In peer, set a local fictional identity, add one line to README saying the peer confirmed the fixed boundary, and commit only README. Then push main to the local remote. Return to script-project and inspect:

git fetch origin
git log --oneline main..origin/main
git diff main..origin/main -- README.md
git merge --ff-only origin/main

Fetching updates remote-tracking information; it does not itself change your current working commit to the peer's commit. Inspect before integrating. The explicit fast-forward works here because the exercise has no local divergence. A real collaboration may need a merge decision, review approvals or a pull request rather than direct pushes to main.

GitHub provides hosting and collaboration features around Git. A pull request communicates a proposed change and its evidence; it is not automatic proof of quality. Configure branch restrictions, required checks and review permissions according to the project, and verify them on the actual service. The offline lab does not claim to have enabled those protections.

Create a conflict over collection scope

The next exercise changes a documentation fixture, scope.txt, not the classifier. Create a branch named docs/collection-scope, add scope=visible-txt as its sole line and commit it. Switch to main and fast-forward that branch. Then create docs/hidden-scope, change the line to scope=visible-and-hidden-txt and commit.

Switch back to main, change the same line to scope=visible-top-level-txt, and commit. These branches now contain different edits to the same base line. Run git merge docs/hidden-scope. It should stop with a conflict; status reports an unmerged path.

Inspect the file in your editor and the proposed histories. Conflict markers describe competing text, not which requirement is correct. Choosing “ours” or “theirs” mechanically can discard a needed clarification or approve unreviewed scope. Our exercise owner has approved visible, nonrecursive collection only, so the resolved file must contain exactly:

scope=visible-top-level-txt

Stage that reviewed resolution, inspect the cached diff and commit the merge with a message explaining the scope decision. Run the classifier tests again. They should pass because the scope document does not change classifier behavior, but they do not validate a future file collector's scope. That separate requirement needs its own collector tests.

Exercise: when should a merge be aborted?

Suppose there is no owner decision on hidden files and they may contain credentials. What should the reviewer do? What if the conflict also includes uncommitted work made before the merge?

Worked reasoning

Pause the scope expansion and obtain an authorized decision rather than picking a side to remove the conflict. In a clean isolated lab, git merge --abort can return from the in-progress merge. In a dirty real tree, do not assume every prior edit is perfectly reconstructible: preserve and inspect the existing work before beginning recovery. A resolved textual conflict is not proof that the resulting behavior meets its requirement.

Worked laboratory solution

Compare your reasoning with the worked solution

The missing test is exactly 10, expected OK. It fails on the old inclusive comparison and passes on the strict comparison. Keep 9=Alert and 11=OK as neighboring checks. The unrelated configuration rename expands risk and should be removed from this change or reviewed as a separate justified task. The ideal diff includes the boundary fix, regression test and any necessary concise documentation. A passing suite without the exact-boundary test would not demonstrate the reported bug was addressed.

Official reference for further study

Workbook already downloaded

Recover safely and defend the complete change

Revert is a new change, not an eraser

Use git log --oneline to find the exact repair commit created in Chapter 2. In this isolated exercise only, run git revert --no-edit REPAIR_COMMIT, replacing the placeholder with that inspected commit ID. This appends a commit reversing the repair. It does not erase the earlier commit from history.

Run the tests again. The exactly-10 boundary fails because you deliberately reintroduced the starting defect. Capture that failure. Reverting can restore undesirable behavior; it is not synonymous with “make safe.” Recovery must be verified against the requirement and the business impact.

Next inspect the revert commit ID and revert that commit. The repair returns through another new commit. All five tests pass. This is a useful demonstration when changes are already shared: recovery is visible and reviewable without rewriting peers' existing history. Conflicts are still possible in real repositories; the tiny fixture does not establish universal automatic reversibility.

Understand the risk of alternatives

History-changing commands and working-tree discard operations solve different problems. Do not choose them just because someone calls them “undo.” Ask whether a change is committed, shared, staged, unstaged or untracked; identify the exact target and recoverability. Destructive resets, broad clean operations and force pushes are intentionally absent from this lab.

A local commit can help preserve a deliberate checkpoint, but a repository stored on one disk is not an independent backup. A remote also is not a secret scrubber or a retention policy. Decide where authorized backups live and how you would recover the repository and its dependencies after losing the machine.

Investigate a misleading passing check

Imagine that the repaired working directory passes but the peer clone fails at 10. List at least three plausible causes before changing anything: the repair was never staged; the staged snapshot predated the final edit; the peer checked out an earlier commit or branch. Compare commit IDs, cached diffs, status and the peer's file content.

Another trap is changing assertEqual(classify_free(10), 'OK') to expect REVIEW. That can produce passing tests by abandoning the written requirement. Review the test diff as carefully as the production diff. A changed expected value needs a justified specification change, not merely a desire for green output.

Project A — Catch the broad replacement defect

In a separate temporary copy, replace every occurrence of the text <= 10 with < 10. Predict the endpoint result first. The input-validation expression contains <= 100, so the broad edit changes it to < 100. The 100 endpoint test catches this regression even if the 10 boundary test now passes.

Repair only the intended return expression, rerun all five tests and show the diff. This exercise explains why editing, testing and review are not interchangeable. A correct local change can become an incorrect mechanical rewrite if the pattern does not identify the intended syntax boundary.

Project B — Submit a realistic pull-request brief

Write a review artifact with: a one-sentence requirement; a reproducible failing baseline; the minimal fix; literal expected boundary results; runtime versions; a list of negative inputs; and unverified operational questions. Include the peer-clone commit ID and its test output. State that input is synthetic and no production collector was touched.

Propose a service-specific release workflow: branch creation, restricted destination, review, automated tests, independent clone or clean runner, merge approval and rollback verification. Do not claim it is configured on GitHub until you actually inspect the intended account and repository settings with authorization.

Project C — Resolve a two-part conflict

Extend the scope document to separate visibility from recursion. One branch changes visibility; another changes recursion. Decide whether Git merges the text automatically and whether that automatic result is approved. An automatic merge can combine two individually plausible changes into an unapproved broader population.

Write the required resulting scope and an acceptance matrix before integrating. Include visible top-level, hidden top-level, visible nested and symlink cases. If there is no collector implementation in this repository, label the matrix a proposal, not executed coverage. Textual integration and behavioral verification are distinct achievements.

Acceptance and references

Deliver the initial failing result, the reviewed repair commit, passing five-test output, staging demonstration, independent clone, conflict decision and verified revert/revert-of-revert history. Your review must explain why ignores do not protect already committed secrets and why a staged snapshot can differ from tested working content.

Consult the official Git documentation for git add, git diff, git restore, git switch, git fetch, git merge, git revert and gitignore. For real hosting, consult GitHub's official pull-request, authentication and branch-protection documentation for the actual account setup. No purchased book is required to finish this standalone exercise.

Official references: staging and recording changes, restore, ignore patterns and GitHub pull requests.

Transfer project — changed conditions

Use the supplied deliberately broken capacity exercise in a new repository. Record failing output, make the minimal repair and rerun tests. Inspect staged changes before committing. Add a review note explaining the requirement, evidence and remaining assumptions about numeric validation. Then simulate an upstream change to the same function and resolve the conflict by preserving intended behavior and rerunning tests, not by blindly choosing one entire file.

Practical assessment rubric

Score each dimension 0–2: 0 = absent or materially incorrect; 1 = partly correct with an unresolved gap; 2 = correct, explicit and supported by the supplied evidence or an actual labeled lab result.

  1. Evidence/model: identify the relevant entities, inputs, assumptions and boundaries without inventing facts.
  2. Main result: derive the case-specific expected result, calculation or decision and show the intermediate reasoning.
  3. Failure/boundary: test the changed condition and explain why the original conclusion does or does not transfer.
  4. Verification: supply reproducible steps and expected/observed results; label manual traces as manual, not executed.
  5. Communication/safety: explain limitations, owners and a proportionate next action without unsafe or unnecessary access.

Target: at least 8/10, with no zero in main result or communication/safety. This is a local learning rubric, not an accredited certification standard. A written/manual solution demonstrates reasoning only; operational competence additionally requires the relevant executable lab in an authorized environment. The native multiple-choice score is separate and does not automatically grade this rubric.

Submission template

Remediation

If the main result is wrong, reconstruct the supplied case from the raw inputs before changing code or controls. If the boundary case is wrong, identify the assumption that changed and rerun both the original and changed case. If verification is missing, do not convert a prediction into an observed result. Reattempt the transfer task without copying the worked solution, then explain it to another person.

Official reference for further study

Assessment: explain your decisions

Choose an answer and write your reason before opening each explanation. Then explain why the other choices do not fit the evidence. Use missed questions to revisit the lesson. This knowledge check is only one part of assessment: complete the practical transfer project as well. It does not predict certification-exam success.

1. What does a commit record?

  1. The staged snapshot
  2. Every future edit
  3. The screen display
Answer and explanation

The staged snapshot — Commits use the staged content.

2. Does .gitignore erase tracked secrets from history?

  1. Yes
  2. No
  3. Only after renaming
Answer and explanation

No — Ignoring is not history removal or credential revocation.

3. Which command inspects staged changes?

  1. git status --short only
  2. git push
  3. git diff --cached
Answer and explanation

git diff --cached — The cached diff compares the staged snapshot.

4. You stage a repair and then edit the same file again. What does the next ordinary commit contain?

  1. The staged snapshot, not automatically the later unstaged edit.
  2. Every saved change in the working directory.
  3. Only the last edit made in the editor.
Answer and explanation

The staged snapshot, not automatically the later unstaged edit. — The index is a separate proposed snapshot. Inspect both git diff and git diff --cached, and verify that the tested content matches the intended commit before sharing.

5. You want to unstage capacity.py while retaining its working edit. Which operation fits?

  1. git restore -- capacity.py
  2. git restore --staged -- capacity.py
  3. Delete and recreate the repository.
Answer and explanation

git restore --staged -- capacity.py — The --staged form changes the index without discarding the working edit. A worktree restore can overwrite that edit. Identify the location and recoverability before using an undo command.

6. Reverting the repair makes the exactly-10 test fail again. What should the reviewer conclude?

  1. Revert failed because it did not delete history.
  2. The tests must be changed to agree with the reverted code.
  3. The new recovery commit restored the known defect; recovery behavior still needs verification.
Answer and explanation

The new recovery commit restored the known defect; recovery behavior still needs verification. — Revert adds a reversing change; it is not automatically a safe resulting state. In this lab, reverting the revert restores the repair through visible history, and independent tests confirm the behavior.

7. Which test exposes the reported bug?

  1. Exactly 10% should return OK.
  2. Only 9% should return Alert.
  3. Only 11% should return OK.
Answer and explanation

Exactly 10% should return OK. — The old and new comparisons agree at 9 and 11. The exact boundary distinguishes them.

8. How should the unrelated configuration rename be treated?

  1. Hide it in the commit message.
  2. Remove it from this fix or review it as a separate justified change.
  3. Keep it because any green test suite proves compatibility.
Answer and explanation

Remove it from this fix or review it as a separate justified change. — Unrelated changes complicate review and can introduce untested behavior beyond the stated requirement.

9. After resolving a merge conflict, what evidence is needed?

  1. Assume the absence of conflict markers proves correctness.
  2. Delete the regression test.
  3. Review the merged behavior and rerun relevant tests.
Answer and explanation

Review the merged behavior and rerun relevant tests. — Syntactically resolved files can still implement the wrong logic. Behavioral verification remains necessary.

Use the explained questions above for offline practice. A scored attempt requires the course assessment on CogniSkill.ca.