9

I made some changes that, after testing, I decided not to use for now. Thus I don't want them in the main branch. However, I don't want to discard them altogether (maybe I will need them later?)

What should I do?

The easiest option is to commit them and immediately revert (don't laugh).

I suspect that what I am supposed to do is to create a separate branch, commit there and not merge into main. However, I have never used branches before, so I am reluctant to start if there is a simpler option.

PS. I am the only person who is using this repo, and this is unlikely to change.

sds
  • 861
  • 7
  • 15
  • 16
    if you are the only person using the repo, it probably doesn't matter how you do it – Ewan Jan 03 '24 at 18:50
  • 2
    This is what "git stash" is for. – pjc50 Jan 04 '24 at 09:30
  • 57
    Learn to use branches – ScottishTapWater Jan 04 '24 at 12:53
  • 17
    @pjc50 "git stash" alone will just store things away locally. It won't get added to the repo, much less pushed upstream. It's appropriate for very short-term storage of unwanted changes, but if OP may "need them later", then this is probably not the right option. – jcaron Jan 04 '24 at 15:24
  • "The easiest option is to commit them and immediately revert (don't laugh)." Not an answer, since I don't have much experience with git, but that procedure (commit+revert) is exactly what we do with subversion. So far, we never needed to go back and "revive" those snippets, but it's reassuring to know that we can if we need to. – Heinzi Jan 05 '24 at 14:43
  • 3
    “I suspect that what I am supposed to do is to create a separate branch, commit there and not merge into main. However, I have never used branches before, so I am reluctant to start if there is a simpler option.” Branches are the simplest option that does exactly what you describe. – Giacomo1968 Jan 05 '24 at 21:04
  • 2
    git checkout -b my-shiny-branch; git commit -am 'WIP: felt cute (but unneccessary) might delete later'; git push; git checkout main' – Bakuriu Jan 06 '24 at 09:29

11 Answers11

27

Although the question is different, much of my answer about what to do with abandoned branches applies to this as well.

You say that maybe you will need the changes later. How sure are you that you'll need them? How much later? Assuming that the work will be relevant later, how do you know that the way you did the work will be relevant later?

Personally, I would discard the work. You gained knowledge and experience by doing it once. If and when it comes up again, you'll be able to reevaluate the requirements and build upon your experience to develop a solution.

If you do decide to keep it, then I would commit to a branch, push that up to a remote, and set an expiration date after which you'd delete the branch because the rest of the system has continued to evolve and it no longer serves as a reliable reference for a potential solution to a problem.

Pang
  • 315
Thomas Owens
  • 82,739
  • 8
    +1 for the emphasis on bitrot. It's a natural reflex to not wish to discard the product of one's efforts, but said product is less and less relevant as time passes. – Matthieu M. Jan 04 '24 at 08:06
  • 9
    @MatthieuM.: The bitrot argument also applies to branch history — but part of the point of version control is that it’s extremely useful to retain history for long-term reference, so long as it’s cleanly organised to avoid clutter. Like OP, I’ve often had other material that I wanted to retain discreetly just like branch history, but hadn’t been merged to an active branch and so wouldn’t naturally appear anywhere. – Peter LeFanu Lumsdaine Jan 04 '24 at 11:48
  • 1
    @PeterLeFanuLumsdaine I don't see how bitrot applies to the "real" history of a system. There's a difference between versions of the system at various points in time (demos, releases, deployments to different environments) and a state of the system that was rejected by not integrating the changes. Maintaining the real history has value to understand the evolution over time (and, in some cases, to meet regulatory or contractual requirements). Maintaining unfinished or rejected work doesn't have as much value, especially once you can't easily integrate that work. – Thomas Owens Jan 04 '24 at 12:00
  • 1
    @ThomasOwens: Say you test out several implementations of a feature, in parallel branches A, B, C. The eventual merged version (A', B', C', or some new D) may be a descendant of one, several, or none of A, B, C — but regarldess of that, all three test branches may shed light on the design choices (relevant for future maintenance/refactoring), so may be useful to have available in history; and all will stale at roughly the same rate (unmerged code portions will stale rapidly for mergability-to-main; their buildability as snapshots will stale slowly but surely in the long-term). – Peter LeFanu Lumsdaine Jan 04 '24 at 14:04
  • 3
    @PeterLeFanuLumsdaine I don't see how the code would be useful. The only code that matters is what was actually implemented. If you want to capture information, perhaps consider an ADR. ADRs typically include rejected options and why you rejected them, and if you use textual formats, ADRs are something that you can include with the commits. So when you merge your final implementation, you would also be merging the associated automated tests and the ADR and perhaps make that traceable to an issue in your issue tracker that has even more information. – Thomas Owens Jan 04 '24 at 14:33
  • 4
    Deleting commits is just stupid, you never know in advance if the code will be useful. It may be unlikely, but it's also essentially without cost to keep them as proper commits. ADRs or expiration dates for a branch are more complicated solutions that don't solve any actual problem, the git history can already do everything required here. Bitrot is not an argument, it's clear to everybody that something that happened why back in history can't be directly applied to the current codebase, but that doesn't mean it's not useful. – leftaroundabout Jan 05 '24 at 16:53
  • 1
    @ThomasOwens Sometimes, you just need to try something out, for example to see if you could achieve something using an existing library. In some cases, that experiment lets you build an estimate for the full feature, and overall, someone decide it's not worth it now. Yet, you may have spent a few days finding a workaround to get that lib to work. Often, I can remember 2-3 years later that I've tried something and got it to work at least partly on an experimental branch. That code is still useful to remind me how I got that lib to work, even if it's out of context with the current branches. – Bruno Jan 05 '24 at 17:16
  • I can find looking at experimental stuff I've done years ago still useful sometimes, especially if I have a vague memory as to how I tried something (at the very least, if you find that old bit of code, that can be useful to co-workers (if applicable in the same job). The real question is how to manage those experiments to keep a record of them in the long term. You could split those experiments into different projects altogether, write a little blog or notes. Having an arbitrary deletion deadline just kills the knowledge you've built over time. – Bruno Jan 05 '24 at 17:20
  • 1
    @Bruno In my experience, that doesn't hold. Even if you replace "2-3 years" with "6 months", the workaround is likely to become invalid. The library may have changed and been updated or there's a newer library that's better to use anyway. The frameworks or programming languages may have been updated to change what good practices are or eliminate the need. Your organizational standards may have changed. The important thing is that you have learned. If you want to capture it, write a wiki page or blog post or something. Don't keep it in your source code repository - it doesn't belong there. – Thomas Owens Jan 05 '24 at 17:21
  • 1
    @ThomasOwens It doesn't belong in your main code repository or as a "current" branch, but it can still be useful. The advantage of keeping such branch, even old, is that it's still within the context at the time. Sure, writing a wiki or a blog is great, but that's time consuming: a luxury you may not have once that experiment has been abandoned. If you've spent a week trying to get something to work and decided that it wasn't worth it at the time (typically due to other deadlines), it's hard to convince anyone to spend even a few hours writing a nice small example for your own blog/wiki. – Bruno Jan 05 '24 at 17:29
  • 1
    @Bruno And you think that a branch by itself would offer enough context to allow someone - even yourself - to understand and use the work in the future? I don't buy that. And it doesn't match up with my experience at all. – Thomas Owens Jan 05 '24 at 17:55
  • 1
    @ThomasOwens Sure, you'll lose context, but sometimes, especially if you've managed to get something to work with a library that are not greatly documented, some old fragments of experimental code can be useful. Many times I've remembered, in an unrelated project or part of the project: "oh yeah, we tried that a while back, there was an issue with x/y/z". Finding that old code can help bring back memories. Not finding it can be frustrating (and make the time you've spent on that experiment a pure waste). Branch storage is cheap. On balance, it can be worth it, if managed reasonably properly. – Bruno Jan 05 '24 at 18:14
  • Documenting such code fragments elsewhere, or committing them to a tips and tricks repo, is much better than leaving them in some random branch you might not even be able to find later. A self-answered Stack Overflow question is a great option for a "How the heck do I do X in poorly-documented Y?", for example. Writing documentation is also cheap, and one of the most valuable -- it's just a task that a lot of people don't like doing (or that isn't valued by their bosses). – Matthew Read Jan 05 '24 at 22:00
  • Even in main/production code where it definitely exists, I have occasionally been unable to find some trick I implemented years back and wished I had written it up in a more searchable form elsewhere. – Matthew Read Jan 05 '24 at 22:02
  • @MatthewRead "unable to find some trick" - well, sometimes you can't find code, it's true. But in that case, there's no harm done with having the commits somewhere back in the history: they're hard to see but also don't get in anybody's way / make finding other things harder. Findability is an argument for using normal commits of the changes instead of some ad-hoc "tips and tricks" alternative, both because it keeps the feature away from current code where it would bloat the project, as well as anchored in the actual context where you wrote it in the first place, giving more to search for. – leftaroundabout Jan 06 '24 at 10:27
15

TL;DR - Spent some time learning your tools (Git specifically).

There are good tutorials for git available and you can probably pick up enough to be comfortable using branches in less than 1 hour. I am assuming/recommending that when you work through the tutorial you do so in a new repository (so that you don't impact your current production code/repository).

Keeping the code in your repository clean is important - it's another form of technical debt - if the repository is clean it is easier to follow what happened in the past.

However as long as you make time to do the cleanup before you git push it's not all the important when you commit - I make a lot of commits as I am working, with comments indicating what changes I made. Then before I push I clean up my history using git rebase and push a sanitized history to other developers.

Edit per the comment:

If I was in this position, I would just create a new branch and commit the code there, after a week if I found I didn't need it I would delete the branch.

Locally, I don't think it really matters where you put it (commit to new branch, stash, commit+revert or just throw the code away) if you are going to do a cleanup before you push it, it’s simply a matter of whatever workflow works best for you.

However, if I wanted others to view the code then having it on a separate (pushed/remote) branch makes it clear that this is something you considered, but choose not to move forward with.

DavidT
  • 3,338
6

The easiest option is to commit them and immediately revert (don't laugh).

I suspect that what I am supposed to do is to create a separate branch, commit there and not merge into main.

These are both perfectly good options. If you want to make relatively sure you never lose access to that code then yes commit and immediately revert. That also means you can write an explanation of why you're choosing not to use that code in the commit message when you revert. When you do git blame on the relevant files you will see the reference to the reversion.

If you want the code to be a bit more out of the way and not part of the main history of your project then put it on a separate branch. It's possible at some point that branch will be deleted or someone will get a copy of your code that doesn't include that branch.

Another option is to use a git tag. Tags are like branches but while a branch is intended for work in progress and is frequently updated, tags are intended for finished things or snapshots of particular points in history and are not automatically updated in the same way.

bdsl
  • 2,724
6

No there is no simpler option than using a separate branch if you want to exclude code from main branch.

It's trivial, really:

$ git stash
$ git stash branch scratchpad

Now you moved all useless code into separate branch called scratchpad which you can delete anytime without affecting your main branch. You can also use stash but unlike branches, it's not meant to be used as long term storage, it's about as reliable as keeping data in your recycle bin.

shinyoi
  • 69
  • 1
3

This is just a special case of what to do with branches you've abandoned - I'd highly recommend to make those experiments on separate branches (branching is cheap in Git).

Your intuition of committing and immediately reverting is good, but for me this is too permanent, considering that it becomes part of the project's history although it never was an active part of it.

Git has a concept for fixed immutable code revisions: tags.

If you've used a branch, just follow the instructions in my other answer; if you don't want to use a branch, you would commit, tag, and then reset the current branch to the previous commit.

$ git commit -m "never worked reliably"
$ git tag archive/frobnicator-experiment
$ git push origin archive/frobnicator-experiment
$ git reset --hard HEAD^

This way, the code can still be referenced through the tag, but it's not part of the current branch's history.

3
  1. Switch to a new branch

    git checkout -b experiment
    
  2. Commit the changes

  3. Revert the changes

  4. Merge the branch into master, avoiding a fast-forward so that there will be an actual merge commit.

    git checkout master
    git merge experiment --no-ff
    

The result will be this history:

... A ── B ──────────── C ── D ... ─master
          ╲            ╱
           idea ── undo ─experiment

Advantages:

  • The addition and deletion are clearly grouped together, and can still easily be referenced.
  • There is a continuous history skipping the whole experiment, with an empty diff between B and C.
  • There are no unmerged branches to be kept around. The experiment branch can be deleted without losing the commits.

In fact it's even possible to omit the undo commit, and instead merge from idea directly without actually including the changes. This would however be confusing, since it will look like the changes were taken into master and only the diffs would show they weren't.

2

It depends on how big the chance is that you are going to use the code later.

If it’s like a risky refactor that you just dont want to apply in this period but for 99% you would do that later and the code doesn’t need to touch a lot of other code I would sort of “feature flag” it and already submit it.

It favors “discoverability” of this change that you still need to implement above “the proper way”.

But depends a lot on the change and your tools. I don’t mind dead code in my C# projects.

I even leave commented out code for a while after a refactor so if something weird shows up I can more easily see the mistake that I made as it is right in front of my eyes instead of behind two clicks.

I know it’s a controversial opinion but I maintain two very large projects on my own with 100.000’s of users. Everyone works differently! Come fight me!

Dirk Boer
  • 444
1

You could always make a fork of the main repository, and use that for whatever POC or throwaway code you want to keep out of your main one. You can use git locally to sync from separate remotes in a single clone - ie pull/merge in the code from your fork if after some time you decide you actually want it in your main, and push that to your main remote. Most repository hosting (Github, BitBucket, etc) have mechanisms for creating pull requests or merges between forks of a given project, and you can still use any branching or testing strategy you need.

Derek
  • 208
  • 1
    This is definitely not simpler than making a branch, and even making a branch is something OP was hesitant to do due to complexity and unfamiliarity. – coppereyecat Jan 04 '24 at 21:59
  • All true, but it's a valid option nonetheless. I don't assume people can't learn how to do things if they want to. – Derek Jan 05 '24 at 02:23
1

I found myself simultaneously agreeing and disagreeing with the accepted answer, so I took a day to collect my feelings and write my own answer.

On the one hand, I don't think that erasing the code altogether is a good idea. On the other hand, keeping outdated code that is not going to be documented nor maintained, that is going to remain on a forgotten branch and that no one is going to dare touch because they don't remember why it's there and don't know what it is, that is going to pollute your workspace, and that is not even going to work anymore because too many other things have changed around it, doesn't sound like a good idea either.

So if you want to keep this code, I think a branch on a git repository is not the right place.

Instead, I suggest writing a journal. Make an entry for this piece of code. Detail the problem that you were trying to solve when you wrote this code; write why you wrote the code this way and not another way; and write why you ultimately decided to abandon this code and not integrate it in the main project.

Make sure to mark the date and add relevant keywords, so that you can find this entry again in the future if you need it.

If you ever find yourself working on a similar problem in the future, you should be able to find that entry in your journal, and the accompanying explanations will help you decide quickly whether a similar approach might work on the new problem or whether the reasons-to-abandon-this-code still apply.

Stef
  • 136
1

Firstly, it's worth learning about Git branches and how to use them. At the very least, you should learn how to create them and commit code to them. You can learn later how to merge, rebase and cherry-pick if required.

The problem you will have is how to manage those experiments in the long term. Depending on what you do, you may find some of these experiments useful much later (possibly years).

Experiments may be abandoned in your project, but the main goal is to keep track of what you've learnt.

In an ideal world, you'd write a small, separate project that's a proof of concept for what you were trying to do. You may even want to explain everything in a blog/wiki associated with the project.

That should generally be your preferred option, but that may require time that you don't have. I'm guessing that if you (or someone else) has decided to give up on that experiment, it's because there were other constraints that pushed you to work on something else as a higher priority. At that stage, spending a few hours writing nice notes might just not be an option, unfortunately.

Also, there might be some benefit in keeping the experiment in the context of the full code at the time, even if your main branch evolves into something completely different later. (At the very least, you might be able to run that old proof of concept at a later date to remember what you were trying to do, what worked and what didn't.)

The main problem is that keeping old experimental branches in the long term can become messy to manage.

There are a few things that can help:

  • Define a convention to name those branches. That's essential. You could a prefix like experiment_. You could maybe even put a date in that name (e.g.experiment_20240105_feature_X), although that date may vary later.

  • The main subsequent problem is that you might not want to see all of these branches in your working tree or your main remote repository.

    • To address this, you can create a second remote repository where you push those experimental branches.
    • That way, you avoid polluting the main remote repository used by your co-workers and yourself, but you can keep that old code. Tools like GitHub and GitLab can help there if you just want to browse those experimental branches later.
    • You can also delete those experimental branches in your local Git repository.

All this said, if you're going to use experimental branches, try to have commit messages that are reasonably meaningful, more or less as if they'd been intended for your main branch. Avoid messages like "Trying something else...". If you can spare the time, tidy up those experimental branches (e.g. squash what belongs together) before pushing them to your experimental repository.

Long-term storage of experimental branches can be useful, but you still want to give the reader (including your future self) a chance to understand what was going on (as you should with any code).

Bruno
  • 344
0

Put it in a folder or file called "deadcode"

This is not an existing convention as far as I'm aware but it's something I do for personal projects. Sure if I stash or commit the code it's somewhere in git but I'm not recovering old code often enough that I have a streamlined workflow to do it. Add to that the fact that I'm liable to misremember what the old code was and potentially go through that process of digging up something other than what I needed.

So now if I consider some piece of code non-trivial enough that I might conceivably reuse it or reference it in the future but I don't want to worry about compiling / linting, I'll just comment it out and stick it in some "deadcode.kt", "deadcode.go", etc. file.

If it's your repo and you're the only one working on it, then do whatever works for you!

mowwwalker
  • 1,159
  • 2
  • 12
  • 20
  • 1
    I agree. It depends on how big the chance that you are hoing to use the code later. If it’s like a risky refactor – Dirk Boer Jan 05 '24 at 20:32