Ask HN: Do you ever truly use your revision history?
Source control gives you a full history of every change that's ever been made to your codebase since its beginning. At my current company they place a huge value on that history, so much so that they haven't transitioned from SVN to git solely because of the logistical challenge of migrating 30 years of commits.
Obviously the write-only paradigm is useful when reconciling changes with others and when reverting recent, broken changes or recovering accidentally-deleted work. But to me, it seems like there's diminishing value the further back you go. I can't imagine getting much value from trawling through two-year-old commits, much less twenty-year-old commits.
So I ask: at your company and in your experience, do you get value from source-control-arachaeology? And if so, what does that look like in your case?
284 comments
[ 6.2 ms ] story [ 291 ms ] threadAs for commits that are over 2 years old, they still serve a purpose. For a legacy app that I worked on, I had `git blame` ran on every line (vim and vscode both have support), and I was able to see who worked on a block of code last. Sometimes, those developers are still there and available to ask questions which has helped me greatly.
Our case was a tooling policy issue but it should be possible to migrate from SVN to git and keep the change history. You should investigate this option.
- I'm doing batches of 50 at a time (quarterly review)
- the SQL doesn't make any sense in the first place.
(Granted code review systems and ticket systems change overtime)
Git blame on gitlab is also a good way of getting context of why something is there to begin with.
We put Jira ticket IDs in our commits and sometimes that’s useful. But the value tends to be in the content of the tickets as much as the commits.
If we decided to squash everything more than a year or two old into a single commit I doubt it would affect us very much in practice.
I do too, so it's worth noting that you don't have to call it that. I think it was a mistake for Subversion to introduce blame as a cute alias for annotate, but its successors (at least Mercurial and Git) have at least retained annotate as an alternative. So you can git annotate to your heart's content and never blame anyone at all.
I've used git-svn[0] to use git within svn, it's been working flawlessly in my case.
[0] https://git-scm.com/docs/git-svn
Makes it easier to figure out how old a line of code is and (if the commit messages are any good) why it was introduced or changed.
"Fixed formatting"
Which is also why I always separate my formatting and structural changes into two sequential commits. Last interesting change is easy to read, and the previous one is the work of a few extra seconds.
It would be worth switching to git if the current technical costs outweighed the costs of the migration, yes.
I think there's more to it than just "we don't need all the history, just squash it and starting with git would be better" (or even "setup authors file, git svn fetch"), though.
I wish that when the team had migrated from SVN to git, they had used a tool that would have preserved the history. It's very easy to do! I don't know why they didn't. They did it right before I joined the company so I never had an opportunity to show them how.
One of my favorite tricks is to make a file out of all the changes in the history:
and then grep through the file (edit: which I like to do in Emacs—hence the file) to see every appearance of some construct. There's a lot of knowledge in there. It's particularly useful when you remember that you did something, but forget how you did it.In fact, I use git proactively this way, to store things in the version history that I might want to remember later. For example, if I write exploratory code to test out a feature or throwaway code to do some analysis—anything I might want to use again, but don't want to commit to the codebase—I'll add it as a commit and then immediately revert the commit (i.e. make a new commit that deletes what I just added). The codebase remains unchanged, but what I just did is now there forever for future me to recover.
Such an approach only works if your system is small, but I like to work on small systems and prevent them from becoming large systems. There's a beneficial feedback loop here: as you get comfortable working with history, it gives you more confidence to delete things, helping to keep the system small.
I've also found this technique useful for solving the chronic problem with documentation: that it inevitably fails to get updated. When I write something about the code, I commit it and, as above, immediately revert the commit. Now it's permanently glued to the state of the code when I wrote it. When I read it in the future, I can do so alongside a diff of the code from then to now. This makes it easy to see what has changed in the meantime, in which case I can update the document and commit/revert it again.
>I like to work on small systems and prevent them from becoming large systems.
This is very wise!
What you’re doing sounds compatible with that.
Why not use a named stash for something like this? It'll keep your history cleaner, and you can always find the stash by name later.
The nice thing about the approach is that there's only one place to look. I don't think it makes the history less clean, since it only contains things that were at some point, if only briefly, in the system.
> Such an approach only works if your system is small,
I see no reason why this wouldn't scale if you (and other people working on the same codebase) just maintain individual branches (say "dang-braindump"). Just do exploratory/documentation work on that and cherry-pick, rebase -i or git merge --ff --squash --no-commit to skip the reverts.
I've done this a bit.
For several of my $DAYJOB projects I maintain documentation as Markdown files in the project, which get rendered into a website at build time. The project changelog is kept in version control the same way (https://keepachangelog.com).
Several times I've tried an experiment or alternate approach that didn't work out and done exactly this, complete with documentation, so the state is preserved. It's easy to document a prototype if it just means throwing a few paragraphs into a text file with the prototype.
Add a note in the changelog about adding the prototype then commit.
Make the revert commit and add a note in the changelog that you've removed the prototype.
Keeping a good, human-readable changelog as described above makes this strategy more scalable. You can document failed experiments you backed out, features that have been removed, and the like, in a few quick summary lines, keeping devs aware of them across the project's lifespan.
New devs can review it for the big-picture history and use the changelog's revision history to see what commits they need to see for the details.
Using a changelog this way also makes it reasonably possible to delete code but still remember it existed years later, something that's otherwise a surprisingly hard problem (especially if the project has high turnover).
With a text file that summarizes all the project's main line of history in a structured, linear way, it's very simple to extract just what you're interested in or find all the entries for a particular thread of research across history, quickly.
I don't think the tooling around git branches really enables that kind of operation in a quick, easy way, partly due to the inherent nature of branches.
I'd be interested to see what your hypothetical workflow turns out like in practice, though. It's certainly possible I'm just not seeing the potential.
> and then grep through the file (edit: which I like to do in Emacs—hence the file)
Since you already have Emacs, I would suggest you do M-& git log -p RET instead. No need to round-trip the data through a file.
However, I get:
and on pressing return, I only get enough data to fill the buffer.There are some disadvantages. It can mess with git bisect, for example.
Depending on how long it's been there can help you assign a priority, e.g. minor bug has existed for 10 years without anyone noticing is probably not something you have to fix right now. The opposite of that is a nasty bug has existed for 10 years until some data structures or control flow changed and exposed it, so it's not a hard and fast rule.
Once or twice I've seen bugs be introduced by merging huge commits from another branch, so there's lessons to be learned from history too. In this case, avoid large merges with conflicts, especially something you cherry-picked.
Some code got broken and Steve immediately throws Jim under the bus. I look at the commit history, and sure enough git blame shows Jim broke it. Except... there was one little problem: I was the one who signed off on that code. I was specifically looking for this exact class of bug before I approved it, and was pleasantly surprised to see that the author had already anticipated this problem.
So what the hell happened?
Steve happened. Steve fucked up (another) three way merge and I didn’t catch it this time. I found the original commit hash and sure enough the code was correct. So then I showed Steve, again, what I call a Five Way Merge (3 way merge, then resolve again against both parents) and made it pretty clear this was no longer a strong suggestion and now a demand that he use this method to do merges.
I push to master infrequently. I keep a series of topic branches off of master, one per project phase. For changes that affect other developers, I pull those out and PR them to master, then rebase the topic branch chain once the PR completes. When I switch projects I use git reflog to remember where I was working.
Basically I take advantage of git rebase and use it like time travel constantly. Somehow I stay sane..
Though we stand on shoulders of midgets usually, you still get a better view.
"git blame" (or the p4 equivalent) is my usual archaeologic tool in this context, but "git bisect" has been very helpful in others. For the first, it should be easy to look at your current codebase in SVN and see how far back the history goes in any particular area. I've found that bisection is most useful for relatively recent history, because I usually have wanted to build or run the software to test for a bug or something - beyond some point in history that becomes impractical.
Moving from SVN to git shouldn't require losing history though...
But lately I’ve been delving into some of the early architectural changes, trying to figure out why a bunch of things get loaded and seemingly never used/only used once... and sure enough someone did some sort of single commit repository split or bull transfer into p4 in the first place... so I have no clues why.
And yes, I use commit history all the time. Fewer secondary bugs from bug fixes. Fewer lines changed per fix, and fixing bugs nobody else can figure out. Started when someone was furious that a bug had been reintroduced twice. Two devs were alternating fixes for two bugs that caused each other. Good times.
If anything I want more commit history. I want to be able to go back and add notes to commits for posterity, or at least for myself in six months when I have forgotten because I haven’t looked at this module once in that time.
Interesting idea - how about using tags for this?
1. Why did you switch? Are you satisfied with the new experience?
2. Why was some of the history needed to be squashed? Were there any technical concerns?
1b) Absolutely! The switch from p4 could've been smoother, but git and access to the associated ecosystem is far ahead of Perforce for everything except storing binaries. We've been abusing p4 by storing electronics CAD files and similar, and do need to put some effort in to a new solution there. For source code, git (and the ecosystem of modern tooling it gives access to) is a huge improvement over p4.
A particular improvement has to do with network latency. Working from halfway around the world, I notice that p4 operations involving many files are very much slower than the similar git operations.
2a) I wasn't involved, but the particular project mentioned above had moved within the depot at some point, so guess the conversion tool that was used to move it couldn't manage that move. I intend to rebuild the older history in git, then see how viable it is to use git-replace to stick it on the beginning of what we have now.
2b) Yes. However, nontechnical concerns dominated conversation by far - to the detriment of the technical concerns.
It's called software archeology. It's not important if you keep exactly the same people working on the same project and they have perfect memory. But if you, say, move people between different teams, or lose people, or hire people, it's a gold mine.
Especially if I have written them since when someone asks me how something works or why it's written that way I can read the commit body and explain it to them/refer them to the message (otherwise my answer is, I don't remember!)
Additionally if you choose your changes well and don't squash commits it can be a good guide to what else touches the thing I'm looking at.