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.

Reply via email to