In the last few years I've been using Working Copy on iPhone/iPad to refine README, code comments, and func/var naming, as part of feature development.
Doing this on devices without the ability to change code has been a big quality driver for me. The draw back is a few unconventional commits at the end of a feature branch.
The commit history can easily get messy, with checkpoint
or the evil twins typo
and update
. Passing temporary changes on my feature branch, up into GitHub, so I can view changes on multiple devices gets a little ugly.
I posted a question about how others have solved this, about what process others use. @ridays2001 gave a good solution 👍
TL;DR
Create a throw away WIP branch from the feature branch, and pull the changes back to your feature branch with a merge --squash
.
$ git checkout -b kitchen_orders
# do main code changes
# setup your wip branch and make accessible
$ git checkout -b wip_kitchen_orders
$ git push --set-upstream origin wip_kitchen_orders
# do minor updates and changes on this branch
# pull wip changes back onto feature branch
$ git checkout kitchen_orders
$ git merge --squash wip_kitchen_orders
# commit the wip changes as one
$ git commit -a -m 'improves godoc comments'
# clean up wip branch
$ git push origin --delete wip_kitchen_orders
$ git branch -D wip_kitchen_orders
These can all be aliased within the shell.
How it works
Here's a summary write-up showing what you need to know, for multi-device changes with a clean git history.
I'm building out my fictional restaurant app, and want to add store and retrieve kitchen orders.
A feature branch for this change:
$ checkout -b kitchen_orders
Switched to a new branch 'kitchen_orders'
I do a bunch of changes as normal, and end up with:
$ git log --oneline
a45fa9e (HEAD -> kitchen_orders, origin/kitchen_orders) adds kitchen order datastore
2f77e62 adds swp to gitignore
4491447 adds fsvault external package
80df0ca adds config pkg to kitchen
Before I create a PR to merge back to develop
, I want to read through the changes and make sure I will understand it in three months time. In a team environment this helps make PR reviews easier too.
So I create a WIP branch from my feature branch, and push that to Github.
$ git checkout -b wip_kitchen_orders
Switched to a new branch 'wip_kitchen_orders'
$ git push --set-upstream origin wip_kitchen_orders
branch 'wip_kitchen_orders' set up to track 'origin/wip_kitchen_orders'.
This WIP branch is for messy commits, and is used to push and pull changes between devices (iPhone, iPad). It lets me do my own code review in a cafe with a pastry, in a civilised way 😁
For me, this code review process is almost more important than the actual code. It's really a review of how understandable I'm leaving things for my future self.
Depending on the feature/change I may make many updates to improve the readability over a few days, with whatever device I have to hand.
Typically this is what I end up with. A bunch of meaningless commit messages, but essential refinements underneath.
$ git log --oneline
a04d7a6 (HEAD -> wip_kitchen_orders) typo
dadc12a stupid typo
8c0dd3c updates function godoc comments
a45fa9e (origin/wip_kitchen_orders, origin/kitchen_orders, kitchen_orders) adds kitchen order datastore
2f77e62 adds swp to gitignore
4491447 adds fsvault external package
80df0ca adds config pkg to kitchen
Now for the magic. I can pull these WIP changes back into my feature branch without a merge commit.
I switch back to my feature branch, and check it's clean.
$ git checkout kitchen_orders
Switched to branch 'kitchen_orders'
Your branch is up to date with 'origin/kitchen_orders'.
$ git status
On branch kitchen_orders
Your branch is up to date with 'origin/kitchen_orders'.
nothing to commit, working tree clean
Then I can merge my WIP branch with squash
to pull over the changes without any commit.
$ git merge --squash wip_kitchen_orders
Updating a45fa9e..a04d7a6
Fast-forward
Squash commit -- not updating HEAD
kitchen/internal/datastore/order.go | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
$ git status
On branch kitchen_orders
Your branch is up to date with 'origin/kitchen_orders'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: kitchen/internal/datastore/order.go
This leaves me able to apply these WIP changes as a single commit on my feature branch, as if the WIP branch never existed.
So I end up with a long term git log graph like this:
$ alias gl='git log --graph --pretty="%C(green) %d %C(red)Date: %ad %C(yellow) %s" --date=human'
$ gl
* (HEAD -> develop, origin/develop, origin/HEAD) Date: 27 seconds ago Merge pull request #5 from thisdougb/kitchen_orders
|\
| * (origin/kitchen_orders, kitchen_orders) Date: 82 seconds ago improves datastore godoc comments
| * Date: 33 minutes ago adds kitchen order datastore
| * Date: 52 minutes ago adds swp to gitignore
| * Date: 54 minutes ago adds fsvault external package
| * Date: 80 minutes ago adds config pkg to kitchen
|/
* Date: Wed May 1 13:57 Merge pull request #4 from thisdougb/thisdougb-patch-1
|\
| * Date: Wed May 1 13:57 Update README.md
|/
* Date: Wed May 1 13:55 Merge pull request #3 from thisdougb/part1b
And remember to clean up:
$ git push origin --delete wip_kitchen_orders
To github.com:thisdougb/go-eat.git
- [deleted] wip_kitchen_orders
$ git branch -D wip_kitchen_orders
Deleted branch wip_kitchen_orders (was a04d7a6).
$
The nice thing about this method is that it's really simple. I can create a WIP branch when I need to, within Working Copy or from another device.
Top comments (1)
Nice post! Thanks for the mention.