git workflow for D

Nick Sabalausky (Abscissa) SeeWebsiteToContactMe at semitwist.com
Mon Dec 4 11:51:42 UTC 2017


On 12/03/2017 03:05 PM, bitwise wrote:
> I've finally started learning git, due to our team expanding beyond one 
> person - awesome, right? 

PROTIP: Version control systems (no matter whether you use git, 
subversion, or whatever), are VERY helpful on single-person projects, 
too! Highly recommended! (Or even any time you have a directory tree 
where you might want to enable undo/redo/magic-time-machine on!)


> Anyways, I've got things more or less figured 
> out, which is nice, because being clueless about git is a big blocker 
> for me trying to do any real work on dmd/phobos/druntime. As far as 
> working on a single master branch works, I can commit, rebase, merge, 
> squash, push, reset, etc, like the best of em.

Congrats! Like Arun mentioned, git's CLI can be a royal mess. I've heard 
it be compared to driving a car by crawling under the hood and pulling 
on wires - and I agree.

But it's VERY helpful stuff to know, and the closer you get to 
understanding it inside and out, the better off you are. (And I admit, I 
still have a long ways to go myself.)

> What I'm confused about 
> is how all this stuff will interact when working on a forked repo and 
> trying to maintain pull requests while everyone else's commits flood in.

Yea. It's fundamental stuff, but it can be frustratingly convoluted for 
the uninitiated. TBH, I really wish we had widespread tools that cater 
to what have emerged as the most common best-practice workflows and the 
basic primitives of those workflows. I even went so far as to get 
started on such a tool (I call it "wit"), but it's been kind of on the 
back burner lately, and it's still far too embryonic for any kind of 
release. (I am still using a git repo for it locally though! Again, 
highly recommeded. At the very least, just because there's nothing worse 
than accidentally loosing a bunch of important code, or finding you need 
to undo a bunch of changes that didn't work out.)

One thing to keep in mind: Any time you're talking about moving anything 
from one repo to another, there's exactly two basic primitives there: 
push and pull. Both of them are basically the same simple thing: All 
they're about is copying the latest new commits (or tags) from WW branch 
on XX repo, to YY branch on ZZ repo. All other git commands that move 
anything bewteen repos start out with this basic "push" or "pull" 
primitive. (Engh, technically "fetch" is even more of a primitive than 
those, but I find it more helpful to think in terms of "push/pull" for 
the most typical daily tasks.)

> How does one keep their fork up to date? For example, if I fork dmd, and 
> wait a month, do I just fetch using dmd's master as a remote, and then 
> rebase?

Yes. "pull" from the official ~master to your local repo's ~master, if 
necessary rebasing your changes on top of the new ~master. Although 
generally, you shouldn't have much (or any) changes in your own ~master 
branch, so typically the rebase part really shouldn't be needed at all, 
since you shouldnt have any local changes on ~master which would need to 
be rebased (this ideal is a situation git refers to as "fast-forward").

Unless, of course, you happen to be futzing around making some changes 
and making your commits to your ~master (which you're not *supposed* to 
be doing anyway - standard best practice is to do all your work within a 
branch). In this case you probably will need to rebase. (The other 
alternative to rebasing is always a merge, but in the specific situation 
you're describing, rebase is definitely cleaner and will lead to less 
problems).

> Will that actually work,

Yes.

> or is that impossible across separate 
> forks/branches?

Totally possible. In fact, that's exactly the sort of stuff git is 
designed to handle.

> What if I have committed and pushed to my remote fork 
> and still want to merge in the latest changes from dlang's master branch?
> 

You pretty much already got this right. First, you do just as you said 
above:

1. Pull from the official repo's ~master to your local repo's ~master 
(rebasing, if necessary, any commits you may have on your local ~master. 
Although, like Bastile said, if you're making local commits to ~master 
then *technically* "you're doing it wrong").

2. And then, after you've pulled (and maybe rebased) the lastest 
official updates to your local machine...maybe then you added some more 
commits of your own...then you can push it all from your local machine's 
clone to your remote fork.

Think of your remote github fork as the "published" copy of your local 
repo. It should exactly mirror your local repo (minus whatever 
branches/commits you're not yet ready to unleash upon the world): You do 
your work locally, and whenever you want to "publish" or "make public" 
your local work, you push it from your local repo to your remote github 
fork. That's all your remote github fork is: A copy of your whatever 
parts of your local repo that you've chosen to publish.

> And how does a pull request actually work?

Those two steps I outlined above? A pull request is the step 3:

3. After you've done steps 1 and 2 above, go to your remote fork on 
github.com, go to whatever branch you were making your changes on (you 
*were* making all your changes in a separate branch and not ~master, 
right? Because otherwise, doing another PR before your last one is 
merged becomes a big PITA - that's why people are so adamant about doing 
all your work in separate branches even though it's honestly a bit of an 
administrative pain to make a branch every time there's a change you're 
brewing in your mind.) Then, hit the big button to make a PR out of your 
branch. The PR tells the others you want them to pull the commits from 
your branch on your github remote repo, into their ~master.

> Is it a request to merge my 
> entire branch, or just some specific files?

The entire branch. Or specifically, the commits in your branch. And 
99.9% of the time, the way it works is, your PR proposes they merge your 
"feature-foobar" or "issue 977734" branch into THEIR ~master. And then 
when they approve and merge your PR - there it goes - your commits get 
copied from your branch to their repo's ~master.

> and do I need a separate 
> branch for each pull request, or is the pull request itself somehow 
> isolated from my changes?

You *should* create a separate branch for each pull request unless 
you're a masochist. There's *no* isolation other than whatever isolation 
YOU create. (Not my idea of award-winning software design, but meh, it 
is what it is).

This is why people are adamant about making a separate branch for each 
pull request. *Technically* speaking you don't absolutely HAVE to...But 
if you *don't* create a separate branch for each PR, you're just asking 
for pain: It'll be a PITA if you want to create another PR before your 
first one is approved and merged. And it'll be a PITA if your PR is 
rejected and you want to do any more work on the codebase.

Think of your local ~master as being a direct mirror of the official 
repo. Do your work in separate branches (each to be converted into 
individual PRs), and keep your ~master as your copy of "this is the 
current state of the official project".

 > If anyone can
 > offer any kind of advice, or an article that explains these things
 > concisely and effectively, that would be helpful.

You asked about keeping your fork up-to-date. Like I mentioned before, 
typically your fork should have these branches:

~master: Should be an exact copy of what the official project's ~master 
branch looked like last time you updated.

issue95423: Your work that's going to be your PR to fix bug #95423. 
Starts with ~master and then adds additional commits on top.

foobar-feature: Your work that's going to be your PR to add feature 
foobar. Starts with ~master and then adds additional commits on top.

So, you've got it like that, and your PRs are taking awhile to develop. 
In the meantime, the official project receives a lot of updates, which 
makes your local clone out-of-date. So what do you do?

1. Pull the lastest changes from the official repo's ~master to your 
local ~master. This should be trivial, and git calls it a 
"fast-forward". After all, your ~master is identical to the official 
one, except you're just missing the newest commits.

2. Pull the lastest changes from the official repo's ~master to each of 
your local branches: issue95423 and foobar-feature. For these, you'll 
need to rebase your changes on top of what you're pulling. There might 
be conflicts. If so, you'll need to resolve them.

That's it. Then when you're satisfied with your changes:

3. Publish, by pushing your local issue95423 or foobar-feature branch to 
a same-named branch on your github remote repo (have git create this new 
branch if it doesn't already exist on your github remote repo).

4. Go onto github.com and create a PR out of the issue95423 or 
foobar-feature branch of your github remote repo.

5. Optionally, add more commits to your local branches, push them to 
your github remote repo, and when you do, your PR will automatically be 
updated with the new commits.


More information about the Digitalmars-d-learn mailing list