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.