Search code examples
gitgit-mergegit-branch

Keeping diverging branches in sync with each other


I have two branches A and B which have diverged.

I want to periodically synchronize them with each other (commit most changes from B to A, and commit most changes from A to B).

When merging in either direction, this might involve rejecting entire files, or just portions of a file.

First thing I did was:

git checkout A
git merge --squash B

I don't care about the commit history of B, and in fact I specifically don't even want it.
I just want a commit that says "bring over changes from B".

I resolved all the changes and committed it to A. Then I did the reverse:

git checkout B
git merge --squash A

At this point, git only recognizes a couple of files have changed. Specifically, if I run git diff --name-only A I get a massive list of differences, on the order of 100 different files.

But git merge A only wants to merge changes in about 5 of those files, and the other are completely ignored.

How do I make git attempt to merge any files which differ between the two branches?


Solution

  • Everything as expected.

    • Here is a demo to show you how it work (as you already know :-))
    • At the end of the script you will see how "git" squash the commits and "fix" the different files as you described them
    #!/bin/bash
    
    ###
    ### Merge conflict demo
    ###
    
    # Create a new demo repository
    rm -rf   /tmp/tempRepository
    echo -e ""
    echo -e "* Preparation(s)"
    echo -e ""
    
    mkdir -p /tmp/tempRepository
    git init /tmp/tempRepository
    cd       /tmp/tempRepository
    
    echo -e "------------------------------------------------------------------------"
    echo -e "$ git checkout -b branchA"
    echo -e ""
    
    # Create a new branch
    git checkout -b branchA
    
    # Add some content to it
    echo -e "------------------------------------------------------------------------"
    echo -e "* Initial commit to branchA"
    echo -e ""
    echo  "Hello World" > hello.txt
    git   add hello.txt
    git   commit -m "Initial commit"
    
    # Create a new branch from branchA
    echo -e "-------------------------------------------------------------------------"
    echo -e "* Create branch B branchA (and dont switch to branchB)"
    echo -e ""
    echo -e "$ git checkout -b branchB"
    echo -e ""
    echo -e "git branch branchB"
    git branch branchB
    
    # Add some content to it (and generate conflict)
    echo -e "-------------------------------------------------------------------------"
    echo -e "* Create change in branchA (after branchB was created from A)"
    echo -e ""
    echo  "Hello World2" > hello.txt
    git   add hello.txt
    git   commit -m "Commit on branchA"
    
    # Add some ramdom commits to branchA
    echo -e "-------------------------------------------------------------------------"
    echo -e "* Add random content to branchA"
    echo -e ""
    for i in {1..5};
    do
        echo  "$RANDOM" > A-$RANDOM.txt
        git   add .
        git   commit -m "Commit [$i] on branchA"
    done
    
    # Add some ramdom commits to branchB
    echo -e "-------------------------------------------------------------------------"
    echo -e "* Checkout & Add random content to branchB"
    echo -e ""
    
    git checkout branchB
    for i in {1..5};
    do
        echo  "$RANDOM" > B-$RANDOM.txt
        git   add .
        git   commit -m "Commit [$i] on branchB"
    done
    
    # Checkout branchA
    echo -e "-------------------------------------------------------------------------"
    echo -e "$ git checkout branchA"
    echo -e ""
    git checkout branchA
    
    # Merge branchB into branchA with squash
    echo -e "-------------------------------------------------------------------------"
    echo -e "$ git merge --squash branchB"
    echo -e ""
    git merge --squash branchB
    
    # See the diffrence
    echo -e "-------------------------------------------------------------------------"
    echo -e "$ git diff --name-only branchA"
    echo -e ""
    git diff --name-only branchA
    
    # Wait for user input
    echo "Press any key to continue..."
    read -n 1
    
    # Check the staging area
    echo -e "-------------------------------------------------------------------------"
    echo -e ""
    echo -e "$ git status"
    echo -e ""
    git status
    
    # Commit the changes
    echo -e "-------------------------------------------------------------------------"
    echo -e ""
    echo -e "* Commit the changes (results of the squashing)"
    echo -e ""
    echo -e "$ git commit -m"Cool commit""
    echo -e ""
    git commit -m"Cool commit"
    
    # View the list of chanegs files
    echo -e "-------------------------------------------------------------------------"
    echo -e ""
    echo -e "* Verify that all is "fixed""
    echo -e ""
    echo -e "$ git whatchanged --oneline  | cat"
    echo -e ""
    git whatchanged --oneline  | cat
    

    Output

    
    * Preparation(s)
    
    Initialized empty Git repository in /private/tmp/tempRepository/.git/
    ------------------------------------------------------------------------
    $ git checkout -b branchA
    
    ------------------------------------------------------------------------
    * Initial commit to branchA
    
    [branchA (root-commit) 5582b4e] Initial commit
     1 file changed, 1 insertion(+)
     create mode 100644 hello.txt
    -------------------------------------------------------------------------
    * Create branch B branchA (and dont switch to branchB)
    
    $ git checkout -b branchB
    
    git branch branchB
    -------------------------------------------------------------------------
    * Create change in branchA (after branchB was created from A)
    
    [branchA ad5738d] Commit on branchA
     1 file changed, 1 insertion(+), 1 deletion(-)
    -------------------------------------------------------------------------
    * Add random content to branchA
    
    [branchA d20f973] Commit [1] on branchA
     1 file changed, 1 insertion(+)
     create mode 100644 A-8451.txt
    [branchA 3690e93] Commit [2] on branchA
     1 file changed, 1 insertion(+)
     create mode 100644 A-18701.txt
    [branchA c90a2fa] Commit [3] on branchA
     1 file changed, 1 insertion(+)
     create mode 100644 A-19933.txt
    [branchA ab06b25] Commit [4] on branchA
     1 file changed, 1 insertion(+)
     create mode 100644 A-8861.txt
    [branchA 2261f61] Commit [5] on branchA
     1 file changed, 1 insertion(+)
     create mode 100644 A-25228.txt
    -------------------------------------------------------------------------
    * Checkout & Add random content to branchB
    
    [branchB ff49491] Commit [1] on branchB
     1 file changed, 1 insertion(+)
     create mode 100644 B-30774.txt
    [branchB 4e96ed8] Commit [2] on branchB
     1 file changed, 1 insertion(+)
     create mode 100644 B-30658.txt
    [branchB 299fd31] Commit [3] on branchB
     1 file changed, 1 insertion(+)
     create mode 100644 B-28765.txt
    [branchB 2bc2c61] Commit [4] on branchB
     1 file changed, 1 insertion(+)
     create mode 100644 B-4777.txt
    [branchB 7321b52] Commit [5] on branchB
     1 file changed, 1 insertion(+)
     create mode 100644 B-6593.txt
    -------------------------------------------------------------------------
    $ git checkout branchA
    
    -------------------------------------------------------------------------
    $ git merge --squash branchB
    
    Squash commit -- not updating HEAD
    -------------------------------------------------------------------------
    $ git diff --name-only branchA
    
    B-28765.txt
    B-30658.txt
    B-30774.txt
    B-4777.txt
    B-6593.txt
    Press any key to continue...
    -------------------------------------------------------------------------
    
    $ git status
    
    On branch branchA
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
        new file:   B-28765.txt
        new file:   B-30658.txt
        new file:   B-30774.txt
        new file:   B-4777.txt
        new file:   B-6593.txt
    
    -------------------------------------------------------------------------
    
    * Commit the changes (results of the squashing)
    
    $ git commit -mCool commit
    
    [branchA 216cca4] Cool commit
     5 files changed, 5 insertions(+)
     create mode 100644 B-28765.txt
     create mode 100644 B-30658.txt
     create mode 100644 B-30774.txt
     create mode 100644 B-4777.txt
     create mode 100644 B-6593.txt
    -------------------------------------------------------------------------
    
    * Verify that all is fixed
    
    $ git whatchanged --oneline  | cat
    
    216cca4 Cool commit
    :000000 100644 0000000 62eb110 A    B-28765.txt
    :000000 100644 0000000 c6d2238 A    B-30658.txt
    :000000 100644 0000000 0694fb8 A    B-30774.txt
    :000000 100644 0000000 87768b1 A    B-4777.txt
    :000000 100644 0000000 179d206 A    B-6593.txt
    2261f61 Commit [5] on branchA
    :000000 100644 0000000 76fdbb7 A    A-25228.txt
    ab06b25 Commit [4] on branchA
    :000000 100644 0000000 d5edada A    A-8861.txt
    c90a2fa Commit [3] on branchA
    :000000 100644 0000000 d69a04c A    A-19933.txt
    3690e93 Commit [2] on branchA
    :000000 100644 0000000 e9880db A    A-18701.txt
    d20f973 Commit [1] on branchA
    :000000 100644 0000000 79e927c A    A-8451.txt
    ad5738d Commit on branchA
    :100644 100644 557db03 b2b6f00 M    hello.txt
    5582b4e Initial commit
    :000000 100644 0000000 557db03 A    hello.txt