0

I have two branches master and i1:

Branch master:

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
    std::cout << "3";
    std::cout << "5";
    return 0;
}

Branch i1:

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
    std::cout << "2";
    std::cout << "4";
    std::cout << "6";
    return 0;
}

Got conflict while merging i1 to master :

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
<<<<<<< HEAD
    std::cout << "2";
    std::cout << "4";
    std::cout << "6";
=======
    std::cout << "3";
    std::cout << "5";
>>>>>>> master
    return 0;
}

Each commit was done in order:

    std::cout << "1";
commit master
    std::cout << "2";
commit i1
    std::cout << "3";
commit master
    std::cout << "4";
commit i1
    std::cout << "5";
commit master
    std::cout << "6";
commit i1

I do merge with Meld:

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
    std::cout << "2";
    std::cout << "4";
    std::cout << "6";
    std::cout << "3";
    std::cout << "5";
    return 0;
}

Is it possible ask merge tool to create merge according to commit history automatically:

int main() {
    std::cout << "Hello World!";
    std::cout << "1";
    std::cout << "2";
    std::cout << "3";
    std::cout << "4";
    std::cout << "5";
    std::cout << "6";
    return 0;
}
shadowtalker
  • 12,529
  • 3
  • 53
  • 96
vico
  • 17,051
  • 45
  • 159
  • 315
  • 1
    This seems like too specific of an edge case to build into Git. You would need some tool with knowledge of C++ syntax to make automatic merges like this. Also it seems very rare that you need to make *exactly* this change, so it's probably not worth anyone's (including yours) time to build and test such a thing. – shadowtalker Oct 04 '21 at 12:14

1 Answers1

0

This is highly specific, but if the following conditions are true (and you implied that they are):

  • The commit datetimes always represent the order the commits should occur.
  • Each commit by itself does the same operation to a contiguous set of lines. (Can this be automated?)

then, instead of a specific merge strategy, you could use the following algorithm to achieve your desired state:

  1. First create a new branch from the merge-base commit:
git switch -c temp-branch `git merge-base master i1`
  1. Now display all the new commits on the two branches that have occurred since the merge-base. The command git log can take in multiple branches and will display all of the commits in reverse chronological order. You can use --reverse to flip that order, and isolate the commits starting from the merge-base for each branch. So, something like this would get the list of commits you need in the proper order:
git log `git merge-base master i1`..master `git merge-base master i1`..i1 --oneline --reverse
  1. Now loop through that list, and for each commit, parse out the change that represents your operation. (Add a new line in your example.) Here's some hints on how to achieve this: Show changes in a commit, and Show only changed lines. Once you have parsed out the change, you can apply this operation to your file. You're ideal scenario would have this automated, as mentioned in the conditions at the top of this answer.

Unfortunately, I believe the implementation of step 3 is strongly tied to your specific use case. It would be nice if you could simply cherry-pick each of the commits listed, but at the first commit from the other branch you're going to get a conflict that needs to be resolved "somehow". But at least that conflict resolution will be simplified on a per commit basis compared to a single merge all at once.

TTT
  • 22,611
  • 8
  • 63
  • 69