-1

I need to identify differences between two branches in a baseless manner. The branches diverge often and only need to be the same when I merge them (once a sprint). They appear to drift even after merging when someone makes a hotfix change to the target branch and it inadvertently doesn't bring some other changes. Either way, git diff shows the branches differ and git merge says there is nothing to merge.

I can use git diff to identify what changes exist, and I have a script that performs a baseless merge using git merge --allow-unrelated-histories. What I'm working on now is backing up to the last merge so I can compare just the merge to the parent.

Consider this git graph:

...-A-B---C---D---E---F---G---H
       \                      ↑
...     \                     main
   \     \          
    I-J---K---L---M---N---O
           \   \ /   /    ↑
            \   f   /     release
             \     /
              --d--
                 

I know the main and release branches. Given release is O I'd like to determine that K is its last merge from main and that commit B was that parent. How do I travese Os history and determine K was the most recent merge and B is its parent?

Determining merges

git rev-list --min-parents=2 <O> would list out all parents and lead me to K though I would need to rule out N and M before that.

Determining parents

I do not know how to do this (given K, determine either B or B & J).

Determine parent's descendents

I do not know how to do this (given B, determine that H is a descendent; and given J, determine that H is NOT a descendent)

Traverse process

If I use git rev-list and similar I'll need to loop over each commit hash returned (to test for parents and parents's descendents). Not the end of the world but if git could do the work for me that would be less error prone.

Determine differences

git diff --name-only <B> <K> would show me file differences between B and K

Perform baseless merge

Meh. A multi-step script involving checkout --orphan and merge --allow-unrelated-histories. I'll leave that out but I have a solution for that.

mlhDev
  • 2,235
  • 1
  • 22
  • 43
  • 2
    Do you know about [`git merge-base`](https://git-scm.com/docs/git-merge-base)? Do you know the difference between `git diff main..release` and [`git diff main...release`](https://stackoverflow.com/a/7256391/7976758)? `git log main...release`? – phd Mar 31 '23 at 15:11
  • That’s a lot of work just to synchronize two branches. Should it be this much work? (Asking the room) – Guildenstern Mar 31 '23 at 15:32
  • @phd no that's really helpful! That would give me `B` now I just need to determine `K`. I'd like to use `git log --oneline release..B -n 1` but only if that would list it in reverse or I could isolate the last commit. – mlhDev Apr 03 '23 at 12:39

1 Answers1

1

When you say synchronize, you mean make branch A look in contents just like B when I merge B? If that is the case, you can do this:

git checkout A
git merge --no-commit B
# I don't want to deal with the details, make it look like B, please:
git restore --staged --worktree --source=B -- .
GIT_EDITOR=true git merge --continue

You can be sure that regardless of what A and B looked like before the merge, git diff B will be empty every single time when that merge is finished.

You could even pull it off with git commit-tree but that's a little more hackish.

eftshift0
  • 26,375
  • 3
  • 36
  • 60
  • This is definitely helpful but doesn't identify the differences. I may replace my entire process with this as it accomplishes the primary goal (make branch A look like branch B regardless) though it is not currently a local operation, I'm using Azure CLI to create a CI-side pull request. – mlhDev Apr 03 '23 at 12:18