If A, B, and C are all independent, then I think it makes sense to checkout a new branch, implement A, submit a PR for this, then go back to the master branch. Then checkout a new branch for B, submit a second PR for this, and then return to the original branch and repeat again for C. So at the end of this, before any of your PRs are reviewed, your tree might look like
--------o master
|---------feature_A_branch
|---------feature_B_branch
|---------feature_C_branch
This lets you create further commits in each branch to address PR suggestions and then when each PR is accepted, you can squash-merge it back into master so that you'd have exactly one commit in master for each of feature A,B, and C.
Of course, this assumes that A, B, and C don't depend on each other at all
Editing to add something about when A, B, and C share code:
If A, B, and C depend on some shared code S, then you might modify the above so that instead of checking out master after finishing A and making a new branch there, you check out to S while the branch with {S,A} is still in PR. This would look something like
---o master
|
|----S---feature_A (with commit for the common shared code)
|---feature_B
|---feature_C
Then, when whichever of A, B, or C pass PR first (lets assume B for concreteness), you'd merge feature_B
back into master
, which would also bring the changes in S to master
as well. Now, you could rebase feature_A
and feature_C
on master
(which post-merge has the changes in S) so then feature_A
only has changes for A and feature_C
only has changes for C. Post rebase and merge, the tree might look like:
---o---S---B (master)
|----feature_A
|----feature_C