-1

I have a local master branch, tracking origin/master, which was forked from (let's say) upstream/stable at some point. I could pull / merge from upstream/stable as changes became available, then send those changes on to origin/master. Everything was good.

Now, I've added a single file, unrelated to the files in upstream/stable, and suddenly my branch is not fast-forwardable.

I could merge from upstream/stable (leading to an annoying merge commit) and push to origin/master, but I suspect that, given the merge commit, my local master branch will still not be ffwd-able from upstream afterwards. Even at times when I don't make any further local commits to master (but still want to constantly update origin from upstream).

Goodbye easy shuttling between upstream and origin; hello nasty ancestry structures (I've seen what repeated merges look in tree view) and useless merge commits.

I don't even know how to experiment with this, as I don't see a way to merge commit-by-commit from upstream/stable, only all the way to its tip.

I know about merge --rebase, but of course that rewrites local history, which doesn't work when local master is constantly synced to origin/master.

What to do?

usretc
  • 723
  • 4
  • 9

1 Answers1

0

You can never fast-forward your branch to another branch if your branch contains changes that the other branch does not[1]. It doesn't matter whether your changes are in the same files or different files; a change is a change.

There are those (and you sound like one of them) who put vain hatred of merge commits above all other concerns; for them, there is git rebase[2]. Each time you get new changes from upstream, you can rebase your local master on them instead of merging them in. Basically your master will, at any point in time, look like you had fast-forwarded it over the entire upstream branch and then made your local changes on top of it. No merge commits. But:

That will mean that, as you noted, your master branch moves in a non-fast-forward way. This is contrary to the normal intent in git, so it means after each rebase you'll have to force push master to origin/master. If your repo is shared, you will have to coordinate every one of those force pushes with all other users, or there is a chance they'll undo your changes when trying to fix the errors that result. You can read more about this issue in the git rebase docs under "recovering from upstream rebase". https://git-scm.com/docs/git-rebase


[1] Fast-forward in git means that instead of merging you just move your branch to the same commit as the other branch because it would have the same result as merging anyway. If your branch has changes in it, then the result wouldn't be the same, and fast-forwarding is simply not possible.

[2] I should note that there are many good uses of git rebase; I don't mean to suggest it's only useful to people with what I consider poor history-management priorities; but it is the primary tool people in that camp can use to get the simplistic histories they think they should have.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • I've been making merge commits for a while now (my question was a simplified version). Today, I looked at the tree structure in `tig`. Horrible. Plus *there is no reality* behind these artificial merge commits -- at least not for repeated ones with no intervening local changes. Before git, `darcs` used to be much smarter about commutative patches, but darcs was slow and it's been dead for a long time. – usretc Feb 27 '21 at 16:26