This article was originally published in Japanese on Qiita and has been translated and adapted for DEV Community.
Introduction
Hello from Japan! ๐ฏ๐ต
I am tosane932, a professional truck driver working in logistics while teaching myself Python.
https://github.com/tosane932/sales_data_app
In workplace safety, there is a concept commonly known as Heinrichโs accident triangle.
It describes a relationship in which one serious accident is associated with many smaller incidents and an even larger number of near missesโsituations where no accident occurred, but something dangerous almost happened.
Recently, while introducing pytest and GitHub Actions into sales_data_app, I experienced three coding near misses in a row.
Fortunately, none of them caused actual damage.
However, precisely because nothing serious happened, I believe they are worth reviewing.
This article records:
- What happened
- Why it happened
- How I noticed it
- What habit prevented it from becoming a real problem
๐ง Near Miss 1: Terminal Output Became File Names
I had left the output from a docker build command visible in my terminal so I could review it.
The log contained lines such as:
=> [internal] load build definition from Dockerfile
=> => naming to docker.io/library/sales-after:latest
Later, I casually ran:
git status
Unexpected files appeared.
Untracked files:
=
CACHED
[internal]
exporting
naming
resolve
transferring
unpacking
After thinking about the cause, I realized that characters such as > and => have a special meaning to the shell.
The > character is used for output redirection.
At some point while copying or pasting the log, part of the text appears to have been interpreted as a shell command.
Words surrounding the redirection symbols were then created as file names.
The actual damage was small.
Only eight empty junk files were created, and they had not yet been added to Git.
However, if I had run:
git add .
without checking first, those meaningless files could have entered the repository history.
Lesson
Always run
git statusbefore using a broad command such asgit add ..
A single confirmation step can prevent unrelated files from being committed.
๐ง Near Miss 2: A New .gitignore Pattern Joined the Previous Line
I wanted to exclude backup files such as:
Dockerfile.bak
from Git tracking.
I added the following pattern to .gitignore:
echo "*.bak" >> .gitignore
When I checked the result, I found this:
sales_data_app_android_demo.mp4*.bak
The two patterns should have been on separate lines.
Instead, they had been joined together.
The cause was that the final line of .gitignore did not end with a newline.
When I appended text using:
echo "*.bak" >> .gitignore
the new pattern was attached directly to the existing final line.
Git then interpreted the entire string as one strange pattern:
sales_data_app_android_demo.mp4*.bak
As a result, neither the .mp4 file nor the .bak files were ignored correctly.
When I ran git status, the .mp4 file appeared as untracked even though I expected Git to ignore it.
That confirmed that the pattern was not working.
Lesson
After appending text with
echo >>, always inspect the file usingcat.
For example:
cat .gitignore
Do not assume that a text file already ends with a newline.
A safer way to guarantee separation is:
printf '\n*.bak\n' >> .gitignore
However, even when using a safer command, checking the final contents is still important.
๐ง Near Miss 3: I Almost Overwrote the Wrong File
This was the most frightening of the three incidents.
I was improving my pytest test code.
The file I needed to edit was:
test_prompts.py
At the same time, I also had the production file open:
prompts.py
Because the file names were similar, I accidentally overwrote the production prompts.py file with the contents of the test code.
Fortunately, immediately after saving it, I felt that something was wrong.
I noticed the mistake and restored the correct contents.
No actual damage occurred.
However, what would have happened if I had not noticed and had pushed the change?
Possible consequences included:
- The Gemini prompt-generation logic used in production could have been replaced by test code
- The application could have stopped working
- The application could have behaved unexpectedly
- The broken production file could have been deployed
- GitHub Actions might still have passed
The final point is especially important.
The test file itself was not necessarily broken.
The mistake affected a production module that may not have been fully protected by the existing tests.
In other words, this was the type of error that could have passed through the test gate I had just introduced.
That is why this incident frightened me more than the others.
Lesson
When editing similarly named files, confirm the file name immediately before saving.
After editing, also use:
git status
and:
git diff
to confirm that only the intended files changed.
For example:
git status --short
shows a compact list of changed files.
git diff -- prompts.py
shows exactly what changed inside a specific file.
The important question is not only:
Does the code look correct?
It is also:
Did I modify the file I actually intended to modify?
Why Tests Alone Could Not Prevent This Mistake
Introducing automated tests improves safety, but tests cannot detect every type of human error.
Tests only protect behavior that has been explicitly covered.
If I accidentally replace a production file and the test suite does not verify that module correctly, the CI pipeline may still show a green result.
That means software safety requires several layers:
- Automated tests
- Static analysis
- Code review
- Git diffs
- File-name confirmation
- Deployment checks
- Runtime logs
A passing test result does not mean:
Every possible mistake has been prevented.
It means:
The behaviors currently covered by the tests passed.
That distinction became very clear during this near miss.
๐ง Summary
None of these three incidents caused actual damage.
However, they all shared one important characteristic:
If I had noticed them slightly later, they could have become real problems.
Like near misses in logistics, these events should not end with:
Nothing happened, so it was fine.
The valuable questions are:
- Why did the mistake occur?
- Why did I notice it?
- Which habit prevented actual damage?
- How can I reduce the chance of repeating it?
In my case:
Near Miss 1
I noticed the junk files because I had made git status a habit.
Near Miss 2
I noticed the broken .gitignore pattern because I checked the file after appending to it.
Near Miss 3
I noticed the wrong overwrite because I felt something was unusual immediately after saving.
None of these required an advanced technical skill.
The difference was whether I performed one additional check.
Small Checks Are the Final Safety Barrier
In truck driving, major accidents are often prevented by ordinary actions:
- Checking mirrors again
- Confirming the loading area
- Inspecting the cargo
- Looking behind the vehicle
- Leaving enough following distance
- Performing a final check before departure
Software development has similar actions:
git statusgit diff- Reading the target file name
- Checking
.gitignore - Reviewing staged changes
- Running tests
- Inspecting deployment logs
These actions are not exciting.
They do not look like major technical achievements.
However, they often form the final barrier between a small mistake and a production incident.
The more I learn programming, the more I feel that coding and truck driving share the same basic safety principle:
Do not depend on everything going perfectly.
Build habits that help you notice when something is wrong.
A Practical Pre-Commit Check
After these incidents, I began thinking of the following sequence as a simple pre-departure inspection.
git status --short
git diff
git diff --staged
Then I confirm:
- Are only the intended files changed?
- Are any strange untracked files present?
- Did
.gitignorework? - Did I accidentally modify a production file?
- Are secrets or temporary files included?
- Does the staged diff match the commit message?
Only after that do I commit.
git add <specific-files>
git commit -m "..."
Whenever possible, I prefer adding specific files instead of immediately using:
git add .
This takes a little longer, but it makes the cargo being committed more visible.
Final Thoughts
These incidents were harmless.
That does not make them meaningless.
A near miss is valuable because it reveals a weakness before the weakness causes real damage.
This time, I learned that:
- Terminal text can be interpreted as shell syntax
- Appending text can fail when the previous line has no newline
- Similar file names can cause edits to land in the wrong place
- Automated tests cannot replace basic confirmation
-
git statusandgit diffare simple but powerful safety checks
Writing code and driving a truck are different jobs.
However, the last line of defense against human error is often the same:
A series of small, unglamorous checks.
This article is based on actual work logs.
GitHub
https://github.com/tosane932/sales_data_app
Top comments (0)