Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git: store different stages of a file in the index/working tree after conflict

Assume one file is in conflict state with git.

It means that the index contains 3 versions of the file, the previous one, the one from one branch, the one from the other branch.

I would like to checkout version 3 ("theirs") in the working directory, and stage version 2 ("ours") in the index.

Is there a painless way to do that?

like image 930
Olivier Verdier Avatar asked Nov 03 '10 18:11

Olivier Verdier


People also ask

What are the various stages of a file in git?

Git has three main states that your files can reside in: modified, staged, and committed: Modified means that you have changed the file but have not committed it to your database yet. Staged means that you have marked a modified file in its current version to go into your next commit snapshot.

What information does the index file store in git?

The Git index is a critical data structure in Git. It serves as the “staging area” between the files you have on your filesystem and your commit history. When you run git add , the files from your working directory are hashed and stored as objects in the index, leading them to be “staged changes”.

What is the two stage system that git uses to save files?

A save in Git is divided into two terminal commands: add and commit. The combination of these two commands gives you control of exactly what you want to be remembered in your snapshot.

What git moves files to staging area from working tree?

One command I know for this is the git checkout -- filename . This discards changes made to that file in the working directory and replaces them with last staged version of the file.


2 Answers

Probably the most pain-free way is like this.

# Checkout 'their' version from the index into the working tree
git checkout --theirs file

# reset the index to the HEAD version, i.e 'our' branch
git reset HEAD file

Fiddling around with the index with the update-index plumbing shouldn't be necessary unless you've lost your HEAD (so to speak).

like image 63
CB Bailey Avatar answered Oct 20 '22 02:10

CB Bailey


The trick is in "adding one version to the index": that would mark the file as solved (meaning no more "ours" or "theirs").
So it needs to be the last step.

Maybe something like:

git show :3:<filename> > <filename>.theirs # save the "theirs" version in a tmp file
git show :2:<filename> > <filename>        # display the "ours" version in the working dir 
git add <filename>                         # add it to the index
                                           #  (marking the conflicting file as resolved)
move  <filename>.theirs  <filename>        # erasing the file with the "theirs" version
                                           # in the working directory

Not exactly "painless"...


To avoid the temporary file, Jakub Narębski suggests using git update index (a plumbing command) to manipulate directly the index.

--replace --cacheinfo <mode> <object> <path> 

--cacheinfo is used to register a file that is not in the current working directory. This is useful for minimum-checkout merging.

By default, when a file path exists in the index, git update-index refuses an attempt to add path/file. Similarly if a file path/file exists, a file path cannot be added. With --replace flag, existing entries that conflict with the entry being added are automatically removed with warning messages.

like image 38
VonC Avatar answered Oct 20 '22 02:10

VonC