Recommended resources
The freely available resources this lesson will direct you to.
Hello. Last lesson defined a public, fictional AI test-selection project with a clear boundary from any prior confidential work. Before you build its Java, Python, and TypeScript components, you need a repository you can safely show to recruiters. This lesson sets up pre-commit checks, automated secret scanning, and a repeatable history audit. Plan on about 40 minutes, including the short videos, readings, and repository setup.
The goal is not to make leaks impossible. It is to put checks at several different points and know what to do if one fails.
Understand what each guardrail can—and cannot—stop
A Git hook runs on your machine before Git completes a commit. A CI check runs after you submit code to GitHub. A history audit examines commits, including earlier versions of files. These checks answer different questions: “Is this change ready to commit?”, “Does the submitted repository pass its checks?”, and “Did a previous commit contain something that should not be public?”
Watch the mechanics of pre-commit before configuring it.
The easy way to keep your repos tidy.
Watch “The easy way to keep your repos tidy” from mCoding to see where Git hooks live, how pre-commit installs them, and what a failed commit looks like.
Watch hook setup for the relationship between the configuration file and the locally installed hook. Continue through a failed commit; notice that a file changed by a hook must be reviewed and staged again. Finally, watch hook security for why you should use trusted, pinned hook sources.
Secret scanning adds a more consequential failure case than whitespace or malformed YAML. The Gitleaks demonstration below shows a check passing, then failing after a secret-like value is staged. The failed commit is the desired outcome: it creates time to investigate before publishing.

A hook is not a security boundary on its own. It must be installed in each local clone, can be bypassed, and cannot erase a secret from a commit that already exists. GitHub’s explanation of push protection and existing-secret alerts makes that distinction concrete.
Introduction to secret leaks and getting started with GitHub Secret Protection
Watch “Introduction to secret leaks and getting started with GitHub Secret Protection” from GitHub to distinguish preventing a push from responding to an exposure that has already happened.
Watch exposure risk, particularly why deleting a credential from the latest file does not remove it from history. Then watch push protection and existing alerts. Treat these as additional protections, not replacements for local review and scanning; repository settings and feature availability can vary.
For this portfolio, the safest starting rule is simpler than any scanner: only original, fictional project material goes into the repository. Never use a prior-work export, configuration file, screenshot, test dataset, or architecture document as a starting template and assume you can sanitize it later.
Create the local repository and its commit checks
Begin locally so you can inspect and audit the repository before its first public push. Use a new directory for the fictional project. If your Git installation does not support git init -b main, initialize normally and rename the branch with git branch -M main.
mkdir ai-qe-test-selection
cd ai-qe-test-selection
git init -b main
Create a short README.md identifying this as an original prototype using a fictional application and synthetic examples. You do not need to write the full recruiter-facing README yet. Add a .gitignore before generating any code or local configuration:
.env
.env.*
!.env.example
*.pem
*.key
.venv/
__pycache__/
node_modules/
target/
playwright-report/
test-results/
The exception permits a future .env.example containing placeholder names and values only, never working credentials. Ignoring a file keeps an untracked file out of ordinary staging; it does not remove a file already tracked by Git, nor does it clean earlier commits.
The pre-commit documentation explains the two pieces you need: a versioned configuration in the repository and a hook installation in your local .git directory. Read the setup and configuration portions, then return to the example below.
Read the pre-commit project’s documentation to understand which checks are shared through repository configuration and which setup step must be repeated in a new clone.
Under “Installation” and “Quick start,” follow the setup steps through the recommendation to check all files. Under “Adding pre-commit plugins to your project,” continue into “.pre-commit-config.yaml - repos” and “.pre-commit-config.yaml - hooks”; read the mappings for what repo, rev, and id select. Finally, under “Usage in continuous integration,” read the CI guidance for running the same checks outside your laptop.
Gitleaks can be added to the same configuration. Its documentation also distinguishes a scan of repository history from a scan of directory contents; you will use the history mode for the publication audit.
Read the Gitleaks project’s setup and command guidance so you can distinguish its pre-commit hook from an explicit audit of past commits.
In “Getting Started,” read “Installing” and “Pre-Commit,” from installation through hook setup. In “Usage,” find “Commands” and its “Git” subsection; read the scan modes. Focus on why the git mode examines commit patches rather than just today’s files.
Add this .pre-commit-config.yaml at the repository root:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-added-large-files
- id: detect-private-key
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.2
hooks:
- id: gitleaks
These checks address distinct mistakes. YAML validation protects configuration syntax; whitespace and end-of-file checks keep routine changes tidy; the large-file check catches accidental artifacts; the private-key check and Gitleaks look for sensitive material. Pinned revisions make hook changes deliberate. They do not guarantee detection of every password, proprietary document, or sensitive datum.
Install pre-commit using an appropriate Python environment. For the native Gitleaks hook, make sure the Gitleaks executable is also installed and available on your PATH, using an installation method in its documentation. Then install the local Git hook and run the checks against current files:
python -m pip install pre-commit==4.2.0
pre-commit --version
gitleaks version
pre-commit install
pre-commit run --all-files
Review any files a hook changes with git diff; stage an accepted change again before committing. Run git status --short and git diff --cached --name-only before each commit. This quick review matters particularly when a broad git add . could include a newly created file you did not intend to publish.
Test the controls, then run them in CI
Make an initial commit containing only the README, ignore rules, and check configuration. Before committing, inspect the staged filenames and run the hooks:
git add README.md .gitignore .pre-commit-config.yaml
git diff --cached --name-only
pre-commit run --all-files
git commit -m "Initialize public portfolio repository safeguards"
A passing run is useful, but it does not prove that the secret check will reject a finding. After that initial commit, test locally with a temporary, nonfunctional canary that resembles a recognizable key format. Do not use a real credential, and do not push or commit the canary.
printf 'aws_access_key_id = AKIAABCDEFGHIJKLMNOP\n' > scan-canary.txt
git add scan-canary.txt
pre-commit run gitleaks
The intended result is a failed Gitleaks check. If it passes, stop and diagnose it rather than treating the control as verified: confirm the file is staged, Gitleaks is installed, and the hook ran. A scanner may change its detection rules, so the outcome—not the example string—is what verifies this setup. In either case, remove the canary from staging and disk before proceeding:
git restore --staged scan-canary.txt
rm scan-canary.txt
git status --short
Local hooks protect your normal workflow, but someone reviewing a pull request needs an independently run check. Add .github/workflows/repository-guardrails.yml:
name: repository-guardrails
on:
push:
pull_request:
jobs:
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- run: python -m pip install pre-commit==4.2.0
- run: go install github.com/gitleaks/gitleaks/v8@v8.24.2
- run: echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
- run: pre-commit run --all-files
- run: gitleaks git --log-opts="--all" .
This workflow runs the file checks on submitted code and scans the Git history available to its checkout. fetch-depth: 0 is important: a shallow checkout would not provide the complete reachable branch history you intend to inspect. Commit the workflow only after reviewing its staged contents.
CI can report a failed push after the data has reached GitHub. Where GitHub offers secret scanning and push protection for your repository, check its security settings and enable the available protections. Do not bypass a push-protection finding just to make a build green. None of these controls substitutes for a pre-publication audit.
Audit before the first public push
Make the audit a recorded procedure you repeat before first publication and whenever importing material, rewriting history, or preparing a substantial public release. Run it from the repository root:
- Inventory the files that would be published. Run
git status --shortandgit ls-files. Inspect filenames and the content of unfamiliar files. Check for generated reports, screenshots, local datasets, configuration exports, and anything derived from prior work. - Review the reachable commit inventory. Run
git log --all --onelineandgit log --all --name-statusto spot unexpected commits or previously committed filenames. Avoid posting scanner output or sensitive diffs into public issues or CI logs. - Scan reachable history. Run the command below and investigate every finding before publishing:
gitleaks git --log-opts="--all" .
- Check the current tree and final state. Run
pre-commit run --all-files, thengit status --short. Confirm that no canary remains, no check was skipped, and the committed README describes only the fictional project.
The --all audit covers commits reachable from local refs supplied to the scan. It is not proof that no secret exists anywhere: scanners miss some formats, and unreachable local objects or copies held elsewhere are outside that claim. For a new repository, avoid accepting findings into a baseline merely to obtain a passing result.
If you discover a real credential, stop publication. Revoke or rotate it through its provider; removing it from the latest file is insufficient. If it was ever pushed or shared, treat it as exposed and coordinate any history cleanup with those who may have copied the repository. An ignored-file rule or a new “delete secret” commit does not undo the earlier disclosure. Investigate confidential non-credential material with the same seriousness, even if no secret scanner flags it.
Only after the audit passes should you create the public, empty GitHub repository. Using an authenticated GitHub CLI is one option:
gh repo create ai-qe-test-selection --public --source=. --remote=origin
git push -u origin main
Do not add --push to the repository-creation command: keeping creation and publication separate gives you one final review point. Alternatively, create an empty public repository in GitHub’s interface, add the remote URL it provides, and push the audited main branch. Confirm afterward that the repository is public, the workflow runs, and its checks pass. If a check fails, investigate before adding portfolio code.
Key takeaways
Your public repository now has three complementary controls: local hooks before commits, CI checks on submitted changes, and an explicit history audit before publication. The critical judgment is knowing their limits. A clean scan is evidence of a checked repository, not a guarantee that no sensitive material exists; a credential that has already been published requires revocation or rotation, not merely deletion.
Next, you will place this repository work within a 16-week preparation plan, alongside recurring interview practice, portfolio milestones, and application-readiness gates.