If I'm working on a feature, on a branch, I struggle to do that while working 'remotely'.
When I work remotely I don't mean from the kitchen table, in a wfh style. My use-case is doing a couple of hours on a desktop at home, then maybe continuing on the train with a laptop as I travel to see some friends. Or going away for a few days and doing a couple of hours coding every morning.
I also use git history to keep track of progress, or track down rogue commits. So trying to maintain meaningful (one line) commit messages is important.
Through the years I've never found a good way to maintain a meaningful git history, while updating code on different devices. It's often too impractical to commit fully worked features, because I'm not actually finished yet but have to go off somewhere.
I've effectively created a desire line, by committing and pushing whatever I have as a checkpoint
so I can continue the work on another device.
For example. I'm adding a new function as part of a feature, at home on a desktop. I don't quite have time to get it finished before I have to leave for a meeting. But I can use the sixty minute train ride to finish the work, using my laptop.
I'd just commit what's done with a message of checkpoint
. Then twenty minutes later pull changes on the branch from my laptop, and finish it off.
The ideal would be a git log of commits with the checkpoint (or transfer) commits removed, while meaningful commits remain.
But I'm interested to know if anyone else has a better method?
What I'm thinking is somehow automating the following, maybe via an alias function or git hook.
Current state:
$ git log --oneline
9ac99be (HEAD -> feature) meaningful 2
1736b60 checkpoint
5de2fe5 meaningful 1
Move HEAD
back to the last meaningful commit, but leaving the code intact:
$ git reset --soft HEAD~2
$ git log --oneline
5de2fe5 (HEAD -> feature) meaningful 1
9679310 (develop) initial commit
$ git status
On branch feature
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: main.go
Now commit the next change:
$ git commit -m 'meaningful 2'
[feature 6fd925e] meaningful 2
$ git log --oneline
6fd925e (HEAD -> feature) meaningful 2
5de2fe5 meaningful 1
9679310 (develop) initial commit
$ git diff 6fd925e~
diff --git a/main.go b/main.go
index f33752a..8e3863f 100644
--- a/main.go
+++ b/main.go
@@ -4,4 +4,6 @@ import "fmt"
func main() {
fmt.Println("meaningful 1")
+ fmt.Println("checkpoint")
+ fmt.Println("meaningful 2")
}
Top comments (13)
You could also practice continuous integration with yourself (i.e. even though there is no team).
Working in very small steps, the code is ALWAYS in a releasable state, and you only commit to main. If stuff needs to be hidden, use feature flags (a simple implementation can just be a config setting in the code - no need for a fully fledged feature flag product).
Yeah, I do try to do this. But life sometimes gets in the way, more so as a solo dev on projects without a boss 😃
I've found that no matter how small the intention, sometimes I still reach for a
checkpoint
commit.Sure, but what I'm saying is the checkpoint commit doesn't have to be a bad thing to be avoided.
As long as the code compiles/runs, just commit it as though it was a normal part of your workflow. Don't call it a "checkpoint", just describe what and why you've done it like any other commit.
If you are working in small steps anyway, this shouldn't be much different from any of your other commits.
Basically if the code is good enough to keep, it's good enough to make it a "proper" commit, and if it's not good enough to keep you should just delete it and start over in your next coding session. If this feels like you are wasting work, it's because you are working in too large a step.
Also, if your commit history is really bothering you, remember about Git's interactive rebase feature - this allows you to do a lot of tidying afterwards if you feel the need.
The checkpoint isn't bad code, it's just unfinished. And I want to finish it on another device.
You raise a good view though, which maybe modifies the question. If I'm already doing reasonably continuous integration in practice, is it possible to go one level more in granularity?
If I am working on my smallest chunk of change , something that's a single commit sized, is it possible to do that across two devices?
I've been bound by the git way of working for nearly twenty years. The concept that the commit is smallest part of the system, and indivisible. And you must sit still until it's completed.
But how we work has changed. I stopped being office based ten years ago, and stopped 9-5 hours over five years ago. In my mind is something like a cross between git and Google Docs.
Hmm.. just had a thought about creating a public VM with a file sync process. Maybe when I am leaving my desktop I can
sync branch changes
, and do the same on my laptop. I might try and see if that would work in practice.thanks for your feedback, it's making me think 👍
You could just spin up a NextCloud droplet (check it out on Digital Ocean Marketplace).
But I still think you are over-complicating things, and just need to use smaller commits. If you read Kent Beck's description of the TDD process you realise how tiny a commit can or should be.
Ah, I didn't know about NextCloud. Interesting.
Yes, I understand development methodologies. And I also break them when I need to. I'm doing systems development, some data generation, infrastructure code, app development, documentation, etc, all in parallel. I'm building an app solo, which often (always 😂) means non-linear work.
I really do get what you're saying. But the position I find myself in is juggling five repo's concurrently, to develop features and deploy those features and document those features. It would be great to have a team on each stream of work, focused exclusively on that code and feature delivery.
If you're working on something and have to switch devices, you can create a new branch and add a WIP commit. Then, when you are done, you can use
git merge --squash <branch-name>
to squash the WIP commits as one single commit into the main branch.Zsh has this helpful alias for git -
gwip
that automatically adds a WIP commit. You can then usegunwip
to undo the WIP commit. And then you can also do a force push to erase the WIP commit from GitHub history.I encountered a situation similar to yours when I used a dual boot setup. Sometimes I shared projects between both OS on the same laptop. I used to create a new branch, push a checkpoint commit, switch OS, pull, undo the checkpoint or merge with squash if done. Sometimes, I just pushed the checkpoint commits to the main branch, then I used undo commit and force push to erase history.
Ah, that's interesting. Nice, and uncontroversial 😃
Yes, dual boot would bring up the same challenge.
I'm going to give this a go, as it's fairly simple. 👍
thanks
Now into the rabbit hole... 😂
I've just discovered that GitHub lets you modify the merge commit message. You can set it to the PR title (Settings>General>Pull Requests), which is a big help.
This makes the git log more readable:
Here I've done a soft reset on
feature3
.And a summary is simple (with the merge commits set to PR title):
Just need to figure out an alias function and where to apply it. But, getting the checkpoint commit hash, and then doing a soft reset to the preceding commit.
Two things I've done in the past in this situation (neither of which actually use git, please feel free to shout cursed!):
File sync between devices, so I have the exact same state everywhere.. after all git fetch/push are effectively this to a shared repo, but I also have stash, modified things....
Remote dev system, that I RDP/ssh/vnc/etc. into, usually for me this is an Azure VM. Depends on network staying up which might be challenging on trains.
Ha, vnc. Do you remember when Citrix (desktop) arrived on the scene? I think this may be tricky (for me), for the connection issues you mention. On the other hand, things like Google Docs (or any other mainstream note/doc sharing) work fine as part of a fairly random work day. It's interesting that nothing like this sync (as opposed to vnc-like) exists.
Yes, I'm thinking a simple file sync may be useful. Given that I am leaving my desk (iMac) and knowingly going on the road to work on my laptop. So
$ sync_my_wip
would be easy.I've been toying with @ridays2001 suggestion. It looks pretty neat, and easy.
Explicitly branching off my feature branch to create a checkpoint/wip branch, where I don't care about commit messages:
And then the same graph when I'd squash the merge of my wip branch back into my feature branch, where I get a commit message to say what happened:
I really think this is a cool workflow/solution. And easy with some shell alias functions.
The filesync is what I'll try if this doesn't work out. 👍
You could use feature branches and squash merge them when they are done. Then in your main/master branch, you'll only have one meaningful commit.
I'm old enough to believe squashing commits is bad, because you lose that history. Therefore it's pointless to write commit messages at all. Although I understand that this is not the modern view 😃
The way we old-timers see a summary view, with git log and
--first-parent
:This means we do the squashing just on the view, rather than throw away the meaningful commit information.