On 14/01/20 10:07 -0600, Peter Bergner wrote:
As somewhat of a git newbie and given gcc developers will do a git push of
our changes rather than employing a git pull development model, I'd like
a little hand holding on what my new gcc git workflow should be, so I don't
screw up the upstream repo by pushing something to the wrong place. :-)
I know enough that I should be using local branches to develop my changes,
so I want something like:
git checkout master
git pull
git checkout -b <branchNameHere>
<modify and add new files>
git commit -m "My commit message1"
<modify and add new files>
git commit -m "My commit message2"
<modify and add new files>
git commit -m "My commit message3"
<all done!>
At this point, I get a little confused. :-) I know to submit my patch
for review, I'll want to squash my commits down into one patch, but how
does one do that?
This is Git, there are a hundred ways ;-)
Should I do that now or only when I'm ready to
push this change to the upstream repo or ???
Totally up to you. You might want to squash some commits early, e.g.
to fix silly typos, but keep most of the branch history intact until
the last minute (to help you remember what you changed and why).
That's my preference.
Do I need to even do that?
If it's a long-lived feature branch you might want to keep the
separate commits and merge them all to master preserving the branch
history (don't take my word for it, I can't remember what we decided
should be the policy for such long-lived branches).
If it's just a short-lived branch to change one thing, or fix one bug,
then what you push should be a single, self-contained commit (even if
you happened to develop it as a series of mini-commits locally).
Also, when I'm ready to push this "change" upstream to trunk, I'll need
to move this over to my master and then push.
Strictly speaking, you don't need to. You can push that branch
directly to master: git push origin HEAD:master
That will fail unless the current branch is up-to-date with master,
but would work fine if you've already rebased your branch on master,
or if master hasn't moved since you branched.
What are the recommended
commands for doing that? I assume I need to rebase my branch to
current upstream master, since that probably has moved forward since
I checked my code out.
You can either rebase on the new master (i.e. bring the new stuff from
master into your branch) or the other way around (bring the stuff from
your branch into master).
A pretty straightforward way to do the second way is:
git checkout master
git pull
git merge --squash <branchNameHere>
[resolve any merge conflicts]
[build + test again if your branch was behind master]
git push
i.e. pull the changes from your branch onto master, then push.
This leaves your <branchNameHere> branch untouched, so you still have
all the history locally for future reference.
There are other ways e.g. 'git rebase --interactive master' and
squash all the commits in the branch that way. Interactive rebases are
awesome, and very useful. It's a fairly manual process, but that gives
you full control. Get familiar with it.
Or, to (non-interactively) rebase your branch on master (which you
might want to do periodically anyway, before you're ready to push
upstream):
git checkout master
git pull
git checkout <branchNameHere>
git rebase master
[resolve any merge conflicts]
[build + test]
That's rebased your branch, but not actually squashed the branch
commits yet. You can do that by checking out master and doing a
merge --squash (as above) or just on the branch:
# make this branch's committed state (aka "index") the same as master
git reset master
# but that didn't touch the content of the working directory,
# that still matches your branch, so you can add+commit all the
# files in the working dir that differ from the "index":
git add --all
git commit
This alters your branch's history to be a single commit against
master, which contains all the changes that you'd done on the branch.
I've never used this method, so I hesitate to recommend it. It's the
least obvious way IMO.
And after either of the rebase methods, you still need to get that
single commit onto master to push (unless you're going to push
directly from the branch). So that might be a reason to prefer doing a
"merge --squash" to squash at the same time as pulling the changes
into master (i.e. the first method above).
Also, at what point do I write my final commit message, which is different
than the (possibly simple) commit messages above? Is that done after I've
pulled my local branch into my master? ...or before? ...or during the
merge over?
Doesn't matter. As long as you push a single commit with a good commit
message, it doesn't matter when that was written. Personally I think
doing it at the end when you do the merge --squash to add a single
commit to master.
...and this is just for changes going to trunk. How does all this change
when I want to push changes to a release or vendor branch?
It's pretty similar. Create a branch from the release branch, merge it
back to the release branch.
Personally, I don't usually use branches for backports, because I only
have one in flight at a time. So I'll just make the change directly in
the release branch and push it directly from there. I rarely have
changes for the release branches that require a series of local
commits that warrant their own branch. I go from making the changes to
pushing it in an hour or two, and since I'm not doing anything else on
that release branch I don't need to use separate branches to keep my
work isolated until it's ready.
I guess I'm just looking for some simple workflow commands for both
trunk and release/vendor branches I can follow until I'm a little more
confident in my git knowledge.
I'm guessing I'm not the only one who would like this info, so maybe
someone can add this to our wiki?
Yes but it takes time :-)