Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git allow to lose file changes history during merge with conflicts

Tags:

git

I'm using Git for a long time, but recently faced with the interesting trick that allow you revert the file changes history during merge. Here is the steps to reproduce is:

I have the git repository with two files and one commit:

$ git branch   
  * master
$ git log --oneline 
  80c8d5a Initial commit
$ git log --oneline -- README
  80c8d5a Initial commit
$ ls
  README conflict_file

I'm creating the new experimental branch and changing README and conflict_file file:

$ checkout -b experiment 
  Switched to branch 'experiment'
$ vim README 
$ vim conflict_file 
$ git commit -am "Experimental changes"
  [experiment cdbc988] Experimental changes
  2 files changed, 2 insertions(+)
$ git log --oneline -- README
  cdbc988 Experimental changes
  80c8d5a Initial commit

Going back to master branch and edit conflict_file (to have the conflict during merge):

$ git checkout master 
  Switched to branch 'master'
$ vim conflict_file 
$ git commit -am "Master changes"
  [master ad8b68e] Master changes
  1 file changed, 1 insertion(+)

The status of my repository in the following:

$ git log --oneline --decorate --graph --all
  * ad8b68e (HEAD, master) Master changes
  | * cdbc988 (experiment) Experimental changes
  |/  
  * 80c8d5a Initial commit

Trying to merge with the experimental branch:

$ git merge experiment 
  Auto-merging conflict_file
  CONFLICT (content): Merge conflict in conflict_file
  Automatic merge failed; fix conflicts and then commit the result.
$ git mergetool 
  <merging conflict in conflict_file>

Here is the trick:

$ git reset HEAD README
  Unstaged changes after reset:
  M      README
$ git commit 
  [master 909139f] Merge branch 'experiment'
$ git log --oneline -- README
  80c8d5a Initial commit

I lost the changes and history of README file that was introduced in experimental branch in Experimental changes commit. Could anybody please comment how it's correlate with the idea that Git know about all the changes? Is that possible to avoid this scenario? It could become a problem in our company, because merge is allowed operation for developers, but they accidentally could remove somebody's changes.

like image 300
erkfel Avatar asked Jun 20 '13 00:06

erkfel


People also ask

Does git merge preserve history?

In the Conceptual Overview section, we saw how a feature branch can incorporate upstream changes from main using either git merge or git rebase . Merging is a safe option that preserves the entire history of your repository, while rebasing creates a linear history by moving your feature branch onto the tip of main .

What happens if you get a conflict during a merge?

A merge conflict is an event that occurs when Git is unable to automatically resolve differences in code between two commits. When all the changes in the code occur on different lines or in different files, Git will successfully merge commits without your help.


1 Answers

No history has been lost: The change to README made on the experimental branch is still contained in commit 210fdc1. That it is not part of the merge commit 909139f is solely because you explicitly reverted it before finalizing the merge.

You didn’t say what you expected to happen, so I can only guess what exactly surprised you here. I’ll just point out two likely candidates.

  1. A merge commit isn’t limited to modifying just the files touched since the merge base, or even only the files that have conflicting changes. In fact, it can be completely different from all its parents.

    “Completely different” of course isn’t what one would recommend, because it would break everyone’s assumptions about what a merge does. However, it can make perfect sense to extend documentation files in a merge commit, and resolving certain merge conflicts may require changing additional files.

  2. When you call git log -- some_path, a process called history simplification is invoked. As the man page describes it, git log will try to display only those commits “that are enough to explain how the files that match the specified paths came to be”. In your case, the initial commit is enough to explain the current state of README (because README has still, or again, the same content), so it is all that is shown.

    You may want to use --full-history, possibly together with --simplify-merges, or some other history simplification options. They, as well as the exact rules for including commits (which are more complicated than implied above), are described in the git log man page, with an extended example.

like image 129
chirlu Avatar answered Sep 21 '22 14:09

chirlu