While the definition of technical debt is…
…the implied cost of additional rework caused by choosing an easy (limited) solution now instead of using a better approach that would take longer. (https://en.wikipedia.org/wiki/Technical_debt)
the original cause of some tech debt is a combination of optimism and ego while following a best practice that should be expanded on. The best practice is to always keep code in source control to preserve work product in the event of hardware failure or accidental deletion (or the proverbial bus accident/lottery fortune).
The expansion this practice requires to truly be best is to use either a repository naming convention or a branch naming convention to indicate that source is the first iteration. The lack of this naming convention for initial commits leads to acceptance and defensiveness of early approaches that will often benefit from major refactoring if not complete abandonment.
Developers frequently avoid major refactoring for many reasons. In mature systems it can be a very real risk to do so and should be approached cautiously. However, the dislike of refactoring often impacts very early work where such changes can (and should) be done with ease.
Whether it is ego, optimism, laziness, deadline pressure, or a combination of any or all of the common factors, using naming conventions that make it clear that refactoring or replacement is expected will help to prevent early tech debt that will likely worsen over time.
The next level is to maintain and architecture decision log for the repository and require an entry to that log for any first iteration commits to reach a status where the code will be deployed. Reviewing these decisions periodically will help identify both intentional (assuming an exception log as well) and unintentional technical debt.
© Scott S. Nelson