Git merge update files not changed to source branches

I'm struggling to figure out how the following behavior is good in git. The following is an example that I put together to help illustrate my problem. Many times my team and I get changes / commits in branches that we did not want to go there.

> git init sandbox && cd sandbox > echo "data a" > a.txt && echo "data b" > b.txt > git add -A && git commit -a -m "initial population" [master (root-commit) d7eb6af] initial population 2 files changed, 2 insertions(+) create mode 100644 a.txt create mode 100644 b.txt > git branch branch1 > echo "more data a" >> a.txt && git commit -a -m "changed a.txt on master" [master 11eb82a] changed a.txt on master 1 file changed, 1 insertion(+) > git branch branch2 && git checkout branch2 Switched to branch 'branch2' > echo "more data b" >> b.txt && git commit -a -m "changed b.txt on branch2" [branch2 25b38db] changed b.txt on branch2 1 file changed, 1 insertion(+) > git checkout branch1 Switched to branch 'branch1' > git merge branch2 Updating d7eb6af..25b38db Fast-forward a.txt | 1 + b.txt | 1 + 2 files changed, 2 insertions(+) 

Please note that in this case, the a.txt file is updated, although it was not affected / modified in branch2. In the above scenario, I would expect git to be smart to recognize that a.txt has not been changed in branch2, and therefore, when applying updates to branch1, do not make these changes.

Is there something I'm doing wrong? Yes, I could choose a cherry, and that would be for this simplified example, when I know what I changed, but not really in the real world, when the changes are much larger, and you do not know what could be affected.

To be clear, I do not want this behavior from git.

+7
source share
3 answers

'branch1' and 'branch2' are nothing more than commit pointers. They are states of the history of fulfillment at certain points in time. Thus, when combining 'branch2' into 'branch1', git does a bit more than setting up a common ancestor and tries to apply the changes from both trees together.

Take a simple diagram:

  branch1 E <- branch2 | / v / A - B - C - D <- master 

In the above example, "branch1" indicates the fixation of B and "branch2" points when fixing E This describes more or less the order of operations that you specified above. If you combined 'branch2' into 'branch1', git would find a common ancestor in B , then apply the whole story that exists between B and E to 'branch1', in particular, commits C , D and E

However, you want just E One (bad) solution would be throwing cherries, as you have already determined. A much better solution is to redistribute "branch2" to "branch1", thereby rewriting the history of "branch2" to include only commit E past "branch1":

 git rebase --onto branch1 master branch2 

This leads to what you are looking for and reads like "rebase branch2", which was originally based on master, on branch1. Note that I left the "branch1" pointer from this diagram for simplicity, and E became E' because its hash hash has changed (as is the case with these diagrams):

  E' <- branch2 / / A - B - C - D <- master 

You can get a similar effect with git checkout branch2 && git rebase -i B , and then remove the C and D commit from the interactive reboot session.

In my last work, we regularly came across this problem with isolated function branches. Cut at different points in time from the same production branch, they will pull for unwanted changes if they merge without a reboot. As an integration manager, I regularly rewrote my stories to a common point in the past (latest product release), thereby allowing a clean drain all the way. This is one of many possible workflows. The best answer depends a lot on how your team moves the code. In a CI environment, for example, it is sometimes less important that C and D retrieved along with merges like the ones you describe.

Finally, note that if E depends on any code in C or D , this solution will cause chaos in your story when merging 'branch1' (now containing a set of changes to E' ) back to' master '. If your workflow is incremental, and "branch1" and "branch2" interfere with similar functions and files, merge conflicts will occur as a matter of course. In this case, you may need a closer look at your team’s workflow.

+2
source

If the above commands are fully and correctly entered, then git is correct. Here is what you did:

  • created a repo (the "leading" branch is used by default)
  • added one set of changes (2 new files) to "master"
  • created a branch ("branch1") but did not change it
  • added one set of changes (changed a.txt) to "master"
  • created a branch ("branch2") and was changed to it (this branch includes a.txt change)
  • added one chageet (changed b.txt) to "branch2"
  • switched to "branch1" (contains two original, immutable files)
  • merge (fast forward) using "branch2" (both changes apply: a.txt and b.txt)

This is exactly what you are describing and what exactly is going to happen. Where you were probably mistaken, you thought you were changing a.txt to "branch1" when you really changed it to "master" before creating "branch2", thereby giving the illusion that magically changes to "branch1" from "master" when merging with "branch2", but actually the change came from "branch2".

If you repeat the test , but in step 3 switch to "branch1" ( git checkout -b branch1 ) instead of making a.txt change to "master". I think you will get the merger expected.

+3
source

a.txt is updated in merge although it has not been affected / changed to branch2

But that was sir. Run the whole command, but git merge branch2 , then

 $ cat a.txt data a $ git checkout branch2 Switched to branch 'branch2' $ cat a.txt data a more data a 

I understand that it resides in branch2 in this way, however I did not change / not touch it after branching.

You sent more data a to master . Then you created branch2 from master . Therefore, branch2 will contain more data a .

+2
source

All Articles