Skip to content

Commit efe4b57

Browse files
committed
Add post about experimental features
1 parent 33d59f6 commit efe4b57

3 files changed

Lines changed: 188 additions & 2 deletions

File tree

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/globals.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ body {
6262

6363

6464

65-
--color-foreground-paper: white;
65+
--color-foreground-paper: #e0e0e0;
6666
--color-foreground-secondary: #ccc;
6767

6868
--color-foreground-border: #aaa;
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
---
2+
meta:
3+
title: How to add an experimental feature to your code, without having it in your main version control
4+
description: You might have a really good idea, but its not practical to get it commited to version control. You can keep the feature around for local use with some shell aliases and git commands.
5+
dateCreated: 2025-05-19
6+
7+
tags:
8+
- "software_engineering"
9+
---
10+
11+
I've been infatuated with loggers for development recently. The idea is, I can put log statements in various parts of my application, and it will log the relevant data to a file. This means no having to set breakpoints and enable/disable my debugger, no scrolling back up the developer terminal. I just leave it running and then when I need it I find the relevant log.
12+
13+
Useful as this is for me, it's not practical for me to convince the rest of the organisation to adopt this pattern formally, not in the pull request I'm working on at least. Besides, I'm still working out what the interfaces should be, and interfaces have this nasty habit of being difficult to change once they're being used.
14+
15+
But I still like the tool and I still want to keep using it.
16+
17+
Here's how I keep it around, without having to commit it to version control proper.
18+
19+
The strategy is that we create one shell alias to cherry-pick a commit in to add the feature, and then another alias to rebase that single commit out.
20+
21+
```
22+
A---B (master)
23+
\
24+
C---D---E---F---G (my-branch)
25+
26+
^ ^
27+
the experimental feature commits
28+
```
29+
30+
Let's assume commits D and F are ones where I implement the feature.
31+
32+
33+
**1. Create a single commit that removes the feature**
34+
35+
We'll call this commit Q.
36+
37+
38+
```
39+
A---B (master)
40+
\
41+
C---D---E---F---G---Q (my-branch)
42+
43+
^
44+
removes the feature
45+
```
46+
47+
48+
**2. Revert that commit**
49+
50+
```
51+
git revert Q
52+
```
53+
54+
```
55+
A---B (master)
56+
\
57+
C---D---E---F---G---Q---R (my-branch)
58+
59+
^ ^
60+
removes the feature reverts the removal
61+
```
62+
We'll call this commit R.
63+
64+
Essentially this is a commit that will _add the feature back in_.
65+
66+
The idea is, when we later want to add the feature in, we'll cherry-pick a commit like this to add it in.
67+
68+
However, because we're likely squash merging to master, the commit Q that the revert commit R is reverting, will no longer exist.
69+
70+
ie. after we merge to master, the git tree looks like this:
71+
72+
```
73+
A---B---X (master)
74+
```
75+
76+
Where X is all
77+
78+
```
79+
C---D---E---F---G---Q
80+
```
81+
82+
squashed into one commit.
83+
84+
85+
**3. Transform commit R to a regular commit**
86+
87+
```
88+
git reset HEAD~1
89+
git commit
90+
```
91+
92+
```
93+
A---B (master)
94+
\
95+
C---D---E---F---G---Q---S (my-branch)
96+
97+
^ ^
98+
removes the feature Adds the feature back in
99+
```
100+
101+
We'll call this commit S.
102+
103+
Now, we can selectively call
104+
105+
```
106+
git cherry-pick S
107+
```
108+
109+
to have our feature apply.
110+
111+
112+
**4. Create shell aliases to add and remove the commits**
113+
114+
Add these to your `.bashrc` or `.zshrc` etc.
115+
116+
```
117+
feature_commit=S
118+
feature_commit_message=some-unique-commit-message-here
119+
alias addfeature="git cherry-pick $feature_commit && git commit --amend -m $feature_commit_message"
120+
alias removefeature='added_commit_sha=$(git log --grep="$feature_commit_message" --pretty=format:%h); git rebase --onto "$added_commit_sha"^ "$added_commit_sha"'
121+
122+
```
123+
124+
How this works:
125+
126+
Adding the feature is pretty straightfoward. The content of commit S exists in our local git object store, and git can retrieve it via the SHA S.
127+
When we apply the commit, git will actually give it a different SHA. That's why need to also rename the commit message, so we can later find this applied commit by commit message, not by SHA.
128+
129+
Removing the commit now involves searching the git log for our unique commit message, and then we do a rebase to remove the commit.
130+
131+
We don't want to do a revert, because we don't want to pollute our git history with a whole bunch of applying the feature and removing it. It'll be squashed away anyway, but still.
132+
133+
134+
**5. Tidy up**
135+
136+
Manually remove commit S
137+
138+
```
139+
git rebase -i HEAD~1
140+
```
141+
142+
**6. Create a remote branch containing commit S**
143+
144+
The solution works by commit content existing in your local git object store.
145+
146+
If your laptop died and you hadn't pushed it remotely, you'll have lost it.
147+
148+
**7. You're ready to go!**
149+
150+
Apply the feature with
151+
152+
```
153+
addfeature
154+
```
155+
156+
Remove the feature with
157+
158+
```
159+
removefeature
160+
```
161+
162+
Note that you may need to deal with merge conflicts when you apply the feature.
163+
164+
165+
**8. Updating the feature later**
166+
167+
Apply the feature
168+
169+
```
170+
addfeature
171+
```
172+
173+
Make your changes.
174+
175+
Amend the commit to include the new changes.
176+
177+
```
178+
git add -A
179+
git commit --amend
180+
```
181+
182+
Update your shell rc script to use this new commit SHA.
183+
184+
185+
186+
Let me know if you find this helpful!

0 commit comments

Comments
 (0)