1

At any given moment, we have a master and develop branch and any number of open hotfixes, feature branches, etc.

I'm wondering, short of a shell script, if there is a method to merge a single commit into all of the branches?

Our testing infrastructure allows us to test different branches before merging them into develop and master. But occasionally, we have infrastructure changes that will require universal code changes on all the branches. Right now, we just go into each branch and cherry pick the change into every branch one by one.

Is there a better way to do this? And an extension of this question would be, is there also a way to just force overwrite the entirety of a file on every branch? Because even if done with a script, some branches are likely to have conflicts that will have to be resolved and others will make undesirable automatic merges. But in this case, we would want the entirety of the newly updated file to overwrite every copy at the top of every open branch.

Kyle
  • 376
  • 2
  • 13
  • Does this answer help you? -> https://stackoverflow.com/questions/2329716/merging-changes-from-master-into-all-branches-using-git – raw-bin hood Apr 18 '19 at 00:19
  • One good answer to that question IMHO was a shell command `for BRANCH in `ls .git/refs/heads`; do git rebase master $BRANCH;` I suppose your could also `for BRANCH in `ls .git/refs/heads`; do git checkout $BRANCH; git merge master;` – raw-bin hood Apr 18 '19 at 00:27
  • @rippledj: Iterating over `.git/refs/heads` as **always** a bad idea. See @torek`s answer and https://stackoverflow.com/q/54561601/947357 for details. – A.H. Apr 20 '19 at 22:48

1 Answers1

3

The short answer is no.

The longer answer starts with the fact that you must somehow define "open branches", as that's not a Git concept. A branch name, in Git, is just a label pointing to one specific commit. A branch is often (depending on who is saying the word) some unspecified series of commits that are reachable from this one specific commit, but sometimes it's the branch name.

Once you've tackled that, it's probably a Small Matter of Programming to use git for-each-ref1 to get a list of all branch names, filter it down to whatever you mean by "open", and write a shell script:

... short of a shell script ...

Oops. :-)

The shell script itself tends to be fairly simple: it runs git checkout to switch to the desired branch, then runs either git checkout <hash> -- <path> && git commit or git merge <hash>, with appropriate additional arguments as desired. The merge case has to consider what to do in the event of a merge conflict, and requires that the chosen <hash> be merge-able to produce the desired result, and that's the real hard part: the appropriate <hash> may vary from one branch name to the next, and in all cases, the particular commit to be merged must be created before running the script.

(In place of git checkout <hash> -- <path>, you can also use cp /path/to/external/file <path> && git add <path>, of course.)


1Do not use ls .git/refs/heads as this doesn't handle several cases, including packed references and branches whose names have the form feature/X. Do remember that git for-each-ref needs a namespace to iterate over: the base one is refs/heads, but a more interesting one might be refs/remotes/origin. See the documentation for details.

torek
  • 448,244
  • 59
  • 642
  • 775