commits & changesets

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
astrorafael
Posts: 6
Joined: Mon Feb 15, 2021 10:09 am

commits & changesets

Post by astrorafael » Fri Feb 19, 2021 10:27 am

Hi
I finally got through the pull request admission process. I have basic skills of git, so I have had to learn a few lessons on how to contribute.

One thing that I'm not comfortable with is that apparently your PR has to be structured in change sets, so my whole bunch of modified files and new file had to go in a single commit.

I like to commit early and often in my local repo whenever I have something that at least compiles. So if you use a similar workflow, how do you do it? Do you set up a separate repo four your daily work, then, when ready collect all changes, make a fork and then submit a PR? Or is there an easier way?

stijn
Posts: 573
Joined: Thu Apr 24, 2014 9:13 am

Re: commits & changesets

Post by stijn » Fri Feb 19, 2021 1:12 pm

You make a fork at the start. This is something you only do once. Then you add the forked repository as git origin, so there are 2 git origins: your fork, and the MicroPython repository itself. Then you create a branch locally and work however you please.

Many small commits is good. However: once you have some work done you generally don't want e.g. 10 commits with 'fix typo' and 'fix codestyle' etc: there is really little use in that. Think of it this way: if you come back a couple of years later and whant to look at a file's history or use git blame etc, it is rather annoying to hwav to crawl through many tiny commits which don't contribute much. Instead you want something which looks like microPython's master branch: also small commits, but each doing a clear unit of work making the overall process easy to follow.

So before you get to a PR you typically do an interactive rebase (also handy if you learn to use git commit --fixup and git rebase -i --autosquash, saves time) to get to a bunch of nice and clear commits. Then push the branch, create a PR. If it needs adjustments e.g. to make the CI build happy you can still do that in small commits and push those, but once you reach a point where thos fixes work you normally squash them again into the commits they actually belong to. So that when it's time to actually merge the thing, the maintaners don't have to do that themselves.

Not sure if this makes sense, I could add practical examples if you want :)

astrorafael
Posts: 6
Joined: Mon Feb 15, 2021 10:09 am

Re: commits & changesets

Post by astrorafael » Fri Feb 19, 2021 2:23 pm

Thank you very much for your comments. I have used Git for my personal projects so far. Yes, it makes sense.
I would love to see some examples.

User avatar
jimmo
Posts: 2244
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: commits & changesets

Post by jimmo » Mon Feb 22, 2021 4:40 am

astrorafael wrote:
Fri Feb 19, 2021 10:27 am
I like to commit early and often in my local repo whenever I have something that at least compiles. So if you use a similar workflow, how do you do it? Do you set up a separate repo four your daily work, then, when ready collect all changes, make a fork and then submit a PR? Or is there an easier way?
Here's my exact workflow:

I have a fork of github.com/micropython/micropython at github.com/jimmo/micropython

I cloned micropython/micropython into a local repo (this will create a "remote" named "origin"), and then I add a remote "jimmo" pointing to jimmo/micropython.

Code: Select all

  git clone git@github.com:micropython/micropython.git
  git remote add jimmo git@github.com:jimmo/micropython.git
When I start working on something I fetch origin to make sure I have the latest code from upstream.

Code: Select all

  git fetch origin
then I start a new branch based on the current master

Code: Select all

  git checkout -b my-new-feature origin/master
then I work away, and similar to you, lots of small commits as I'm getting things working.

Occasionally I push this branch up to my fork. The first time, I do

Code: Select all

  git push -u jimmo
to create the branch at that remote. Then later times, I do

Code: Select all

  git push -f
to force update the remote.

Periodically I pull in new changes from upstream via an interactive rebase. Most of the time there's nothing to do -- in the interactive rebase I just see my commits and let it run.

Code: Select all

  git fetch origin
  git rebase -i origin/master
Note that I never use "merge" (and hardly ever "pull".. when I do it's "git pull -r" to force a rebase).

When I'm ready to make a PR, I use interactive rebase to turn it into the commits that I want. There are lots of ways to do this that require varying levels of git knowledge, but the simplest approach I find is to break each commit apart and then recombine them into the final commits.

---

So let's say I've made five commits, that overall do two major things. My goal is to turn each of those five commits into a pair of commits, one for each of those major things.

The first step is to do another interactive rebase:

Code: Select all

  git rebase -i origin/master
Then for each commit I change it to "edit". Then I can use a combination of git restore to take individual bits out of the commit and stage them, then create an additional commit. Getting used to "git add -p" is quite useful here (although most of the time I do this visually using Sublime Merge).

Then you now have a bunch of small commits, that you can then do yet another interactive rebase and put them into the order that you want and use "fix" rather than "pick" to squash them into the previous commits. So now you take your five pairs of commits, and turn them into two commits.

---

The other approach is.. Let's say you've done five commits on your branch and now you want to turn it into a PR (i.e. you want to completely re-do your commits without re-doing the actual work). After rebasing on master, you can "soft" reset it, which will have the effect of unstaging all the changes from those commits and just putting them into your working directory.

Code: Select all

  git rebase -i origin/master  # Just so you're up to date
  git reset origin/master   # Remove all commits relative to master, and turn them back into diffs in your working directory.
Note this is a "soft" reset, which is why the diffs are preserved.

Then you can just use "git add -p" (or Sublime Merge :) ) to select individual hunks to stage, then commit them as you go into the logical commits that you want.

This is definitely the easiest approach for turning the first "proof of concept" into a PR.

---

(Yes, it's a lot of work and git is awful but it's still the best thing in a long list of revision control tools I've used)

astrorafael
Posts: 6
Joined: Mon Feb 15, 2021 10:09 am

Re: commits & changesets

Post by astrorafael » Mon Feb 22, 2021 8:12 pm

Wow, thanks once again for your detailed response. very helpful !

I think, I'll try the second option, seems more straightforward, although I need to be familiar with some concepts first.

Post Reply