- Git Version Control Cookbook
- Aske Olsson Rasmus Voss
- 1000字
- 2021-12-08 12:33:52
Using git rerere to merge known conflicts
While working on a feature branch, you probably like to merge daily or maybe more often, but often when you work on long-living feature branches, you end up in a situation where you have the same conflict occurring repeatedly.
Here, you can use git rerere
which stands for reuse recorded resolution. Git rerere
is not enabled by default but can be enabled with the following command:
$ git config rerere.enabled true
Tip
You can configure it globally by adding --global
to the git config
command.
How to do it…
Perform the following steps to merge the known conflicts:
- In the
jgit
repository folder, start by checking out a branch that tracksorigin/stable-2.2
:git checkout -b rerereExample --track origin/stable-2.2
- Now, change the maven-compiler-plugin version to something personalized such as
2.5.2
like this is in line 211. If you rungit diff
, you should get a result very similar to the following:$ git diff diff --git a/pom.xml b/pom.xml index 085e00f..d5aec17 100644 --- a/pom.xml +++ b/pom.xml @@ -208,7 +208,7 @@ <plugin> <artifactId>maven-compiler-plugin</artifactId> - <version>2.5.1</version> + <version>2.5.2</version> </plugin> <plugin>
- Now add the file and create a commit:
$ git add pom.xml $ git commit -m "Update maven-compiler-plugin to 2.5.2" [rerereExample d474848] Update maven-compiler-plugin to 2.5.2 1 file changed, 1 insertion(+), 1 deletion(-)
- Store you current commit in a backup branch named
rerereExample2
:$ git branch rerereExample2
Here,
git branch rerereExample2
is just storing the current commit as a branch, as we need to use that for rerere example number 2. - Now, we need to perform the first merge that will fail on auto merge. Then, we can solve that. After solving it, we can reuse the merge resolution to solve the same problem in the future:
$ git merge --no-ff v3.0.2.201309041250-rc2 A lot of output … Automatic merge failed; fix conflicts and then commit the result.
- As we have
git rerere
enabled, we can usegit rerere status
to see which files or paths will be recorded:$ git rerere status pom.xml
- Edit the
pom.xml
file and solve the merge conflict so that you can get the diff output shown as follows. You have to remove the line with2.5.1
and the merge markers:Tip
Merge markers are lines that begin with
<<<<<<
,>>>>>>
, or ======
; these lines indicate the points where Git could not perform an auto merge.$ git diff v3.0.2.201309041250-rc2 pom.xml diff --git a/pom.xml b/pom.xml index 60cb0c8..faa7618 100644 --- a/pom.xml +++ b/pom.xml @@ -226,7 +226,7 @@ <plugin> <artifactId>maven-compiler-plugin</artifactId> - <version>3.1</version> + <version>2.5.2</version> </plugin> <plugin>
- Mark the merge as complete by adding
pom.xml
to the staging area and rungit commit
to finish the merge:$ git commit Recorded resolution for 'pom.xml'. [rerereExample 9b8725f] Merge tag 'v3.0.2.201309041250-rc2' into rerereExample
- Note the recorded resolution for the
pom.xml
output from Git; this will not be here without enablinggit rerere
. Git has recorded this resolution to this particular merge conflict and will also record how to solve this. Now, we can try and rebase the change to another branch. - Start by checking out the
rerereExample2
branch from our repository:$ git checkout rerereExample2 Switched to branch 'rerereExample2'
- Try to rebase your change on top of the
origin/stable-3.2
branch:$ git rebase origin/stable-3.2 First, rewinding head to replay your work on top of it... Applying: Update maven-compiler-plugin to 2.5.2 Using index info to reconstruct a base tree... M pom.xml Falling back to patching base and 3-way merge... Auto-merging pom.xml CONFLICT (content): Merge conflict in pom.xml Resolved 'pom.xml' using previous resolution. Failed to merge in the changes. Patch failed at 0001 Update maven-compiler-plugin to 2.5.2 The copy of the patch that failed is found in: c:/Users/Rasmus/repos/jgit/.git/rebase-apply/patch When you have resolved this problem, run "git rebase --continue". If you prefer to skip this patch, run "git rebase --skip" instead. To check out the original branch and stop rebasing, run "git rebase --abort".
- You should notice the following output:
CONFLICT (content): Merge conflict in pom.xml Resolved 'pom.xml' using previous resolution
- As the merge conflict is the same in
pom.xml
, Git can solve the conflict in the file for you. This is very clear when you open the file and see there are no merge markers, as the resolution Git had recorded has been applied. Finish the merge by addingpom.xml
and continue the rebase:$ git add pom.xml $ git rebase --continue Applying: Update maven-compiler-plugin to 2.5.2
- Start Gitk to see that the commit has been rebased on top of the
origin/stable-3.2
branch:
You can try the same scenario with merging and it would merge the file automatically for you.
There's more...
When you merge different branches often and you are not sure which branch a specific error fix is a part of, it is actually quite easy to find out.
- You need to find a commit you are interested in getting this information for. Then, use the
--contains
flag for thegit branch
command:$ git branch --contains 06ddee1 anotherBugFix lastBugFix master newBugFix remoteBugFix remoteBugFix2 remoteOldbugFix * rerereExample2
- The previous command lists all the branches that have the specific commit. If you leave out the
<commit>
option, Git will checkHEAD
. So, for instance, checking out thererereExample2
branch and executing the following command, you will see the commit is present only on that branch:$ git checkout rerereExample2 Switched to branch 'rerereExample2' $ git branch -a --contains * rerereExample2
Tip
The
-a
option indicates that you wish to check all the remote branches as well. If you leave this out, it will check only local branches.However, as you can see, our commit is not on any remote branch as the commit has just been created locally and has not been pushed to any remotes yet.
Tip
You can use tags, branch names, or commit hashes while using the
git branch -a --contains
command. - Let's try to see the branches where the
v2.3.0.201302130906
tag is present:$ git branch -a --contains v2.3.0.201302130906 anotherBugFix lastBugFix master newBugFix remoteBugFix remoteBugFix2 remoteOldbugFix remotePartlyMerge * rerereExample2 remotes/origin/HEAD -> origin/master remotes/origin/master remotes/origin/stable-2.3 remotes/origin/stable-3.0 remotes/origin/stable-3.1 remotes/origin/stable-3.2
That tag is in quite a lot of branches.