git rebasing in a shared feature branch

I've used git a fair bit, but I haven't done a lot of rebasing. My rudimentary understanding is that you should not rebase commits that have already been pushed (this possibly pulled), because rebasing commits actually creates new commits (i.e., the hashes are different). And, in short, this can wreak havoc.


I understand that rebasing can keep the commit history _much_ easier to follow. The Indeni git docs (e.g., https://indeni.atlassian.net/wiki/spaces/IKP/pages/63012870/Pushing+code+git) suggest a workflow that uses rebasing. Specifically:


'Once you've committed your code, you will need to push it to the main repository. Before you do, however, it's important you update your branch with whatever progress the "staging" branch has achieved while you were working on your code. To do that, run "git pull --rebase origin staging".'


This makes sense to me, so long as the local commits haven't been pushed yet. So, the workflow would be "do some work, commit, pull-rebase onto staging, and push". But, what if you're working in a shared feature branch where devs are working on shared code? Chris and I are doing that now. I'm thinking that each dev working on the feature branch should still rebase onto staging before pushing, but would also need to pull in (merge, not rebase) the feature branch before pushing...? This would mean periodic merge commits in the feature branch. In this case, the workflow would be: write some code, commit, pull-rebase onto staging, pull-merge with feature, push...


I guess the problem I'm wrestling with is that it doesn't really seem possible to rebase onto two different branches in a single push. E.g., rebase local feature commits onto staging and then try to rebase those same local commits onto somebody else's feature branch commits (ones that have been pushed to the feature remote while you were making your local changes).


Let me jump and share my thoughts, personally I prefer to use merge because you can keep track with changes more easily. In engineering, before pushing code to develop ( equal to staging for the Knowledge repository) we are merging develop branch into the feature branch, making sure that we have the latest changes and we didn't break anything.

Nice blog post about merge-or-rebase

Having done a little more research, I'm going to try to answer my own question.


Note: if you're thinking about using rebase, and you're not totally sure about it, _please_ do some research and practice with it first; if you don't really understand rebase, you can cause git chaos. Otherwise, just stick with merge. Feel free to ping me if you want to talk about it.


"...what if you're working in a shared feature branch where devs are working on shared code? ....I'm thinking that each dev working on the feature branch should still rebase onto staging before pushing, but would also need to pull in (merge, not rebase) the feature branch before pushing...?"


You could do this, but I don't think it's a good workflow. Given our current requirements (using pull requests), if you want to use "rebase", I think a better way would be (basis is this article that Alon recommended -- merge or rebase):


  • Given branch "staging" and shared branch "feature" (feature could be "fortinet-fortigate" or "cisco-ios")
    • developers Hawk and Chris are sharing feature. They _branch_ from feature to do their work (call them "working branches", IKP-1 and IKP-2). They don't work directly on feature.
    • devs push to their respective working branches for backup
    • from their working branch, devs periodically pull --rebase onto feature.
      • note, once they've rebased, they will have to force push to their working remotes for backup
      • assumes no one else is pulling code from their working remote branches
    • Some dev (e.g., Hawk) periodically merges staging into feature to stay up-to-date with any changes there.
    • When dev is ready for pull request, they do a final pull --rebase onto feature, then force push to working and create a pull request from working to feature (not staging)
    • When pull request is complete, dev can do optional git local git cleanup (interactive rebase, squash commits), do a final force push to working, and merge working into feature. Delete working branch.
    • When feature is ready for staging (and staging is ready for feature), merge feature into staging. Delete feature branch if it's no longer needed.


Just to be clear, you can do all of this without rebase or force push, this is just a way to keep the commit history more tidy.


"...it doesn't really seem possible to rebase onto two different branches in a single push."


I think this is basically right. This all goes back to: don't try to rebase commits that might have been shared. Once you have rebased your working commits onto branch A, if you try to pull --rebase onto branch B, you will rebase your commits _and_ any branch A commits which are not in branch B. Not good. Bottom line: choose one branch to rebase onto, merge in anything else you need.