Show pageOld revisionsBacklinksBack to top This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ===== Overview ===== Both basic and advanced merging operations. ===== SYNOPSIS ===== <code> git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]] [--[no-]allow-unrelated-histories] [--[no-]rerere-autoupdate] [-m <msg>] [-F <file>] [<commit>...] git merge --abort git merge --continue </code> ===== Simple merging ===== ==== Basic merge ==== If you have this situation: <code> A---B---C topic / D---E---F---G master </code> followed by: <code> $ git checkout master $ git merge topic </code> the end result is a new merge commit H: <code> A---B---C topic / \ D---E---F---G---H master </code> ==== Fast-forward merge ==== If you have this: <code> A---B---C topic / D---E master </code> followed by: <code> $ git checkout master $ git merge topic </code> the default fast-forward merge will produce: <code> A---B---C topic / master D---E </code> or, depicted another way: <code> D---E---A---B---C master topic </code> ===== Query containedness and mergeness ===== From ''man git-branch'': <code> With --contains, shows only the branches that contain the named commit (in other words, the branches whose tip commits are descendants of the named commit), --no-contains inverts it. With --merged, only branches merged into the named commit (i.e. the branches whose tip commits are reachable from the named commit) will be listed. With --no-merged only branches not merged into the named commit will be listed. If the <commit> argument is missing it defaults to HEAD (i.e. the tip of the current branch). </code> Examples: <code> $ git branch --merged master $ git branch --no-merged $ git branch --contains v4.19 $ git branch --no-contains v4.19 </code> ===== Dealing with simple merge conflicts ===== Imagine this change on the ''master'' branch: <code> $ git show master commit 4a93eab592cf790838314b3799eb7a4faa213538 (HEAD -> master) Author: Robert P. J. Day <rpjday@crashcourse.ca> Date: Fri Mar 1 08:17:50 2019 -0500 Change to third edition diff --git a/README.asc b/README.asc index fa40bad..9fefbd5 100644 --- a/README.asc +++ b/README.asc @@ -1,4 +1,4 @@ -= Pro Git, Second Edition += Pro Git, Third Edition Welcome to the second edition of the Pro Git book. $ </code> And imagine this clearly-conflicting change on the branch ''4th'': <code> $ git show 4th commit 9e679bc1c27d5d708d571ea1b47564f3a99df944 (4th) Author: Robert P. J. Day <rpjday@crashcourse.ca> Date: Fri Mar 1 08:19:35 2019 -0500 Fourth edition diff --git a/README.asc b/README.asc index fa40bad..1f0879f 100644 --- a/README.asc +++ b/README.asc @@ -1,4 +1,4 @@ -= Pro Git, Second Edition += Pro Git, Fourth Edition Welcome to the second edition of the Pro Git book. $ </code> Trying to merge will generate a //merge conflict//: <code> $ git checkout master $ git merge 4th Auto-merging README.asc CONFLICT (content): Merge conflict in README.asc Automatic merge failed; fix conflicts and then commit the result. $ </code> ''git status'' will tell you that you have a merge conflict; <code> $ git status ... snip ... You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: README.asc no changes added to commit (use "git add" and/or "git commit -a") </code> The merge conflict is identified in the ''README.asc'' file: <code> $ less README.asc <<<<<<< HEAD = Pro Git, Third Edition ======= = Pro Git, Fourth Edition >>>>>>> 4th Welcome to the second edition of the Pro Git book. ... etc etc ... </code> So edit the file and resolve the conflict any way you want, such as: <code> $ less README.asc = Pro Git, Fifth Edition ... snip ... </code> Stage the resolved file: <code> $ git add README.asc </code> You can tell the conflicts are now resolved: <code> $ git status On branch master All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: modified: README.asc $ </code> And commit: <code> $ git commit -m "Bumped merge up to fifth edition" </code> The final version of ''README.asc'': <code> = Pro Git, Fifth Edition Welcome to the second edition of the Pro Git book. ... etc ... </code> ===== Advanced merging ===== ==== Fast-forwarding ==== Recall a fast-forward merge: <code> A---B---C topic / master D---E </code> You may or may not want that: <code> --ff When the merge resolves as a fast-forward, only update the branch pointer, without creating a merge commit. This is the default behavior. --no-ff Create a merge commit even when the merge resolves as a fast-forward. This is the default behaviour when merging an annotated (and possibly signed) tag that is not stored in its natural place in refs/tags/ hierarchy. --ff-only Refuse to merge and exit with a non-zero status unless the current HEAD is already up to date or the merge can be resolved as a fast-forward. </code> ==== Committing ==== <code> --commit, --no-commit Perform the merge and commit the result. This option can be used to override --no-commit. With --no-commit perform the merge but pretend the merge failed and do not autocommit, to give the user a chance to inspect and further tweak the merge result before committing. </code> ==== Editing ==== <code> --edit, -e, --no-edit Invoke an editor before committing successful mechanical merge to further edit the auto-generated merge message, so that the user can explain and justify the merge. The --no-edit option can be used to accept the auto-generated message (this is generally discouraged). The --edit (or -e) option is still useful if you are giving a draft message with the -m option from the command line and want to edit it in the editor. </code> ==== Squashing ==== <code> --squash, --no-squash Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit, move the HEAD, or record $GIT_DIR/MERGE_HEAD (to cause the next git commit command to create a merge commit). This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus). With --no-squash perform the merge and commit the result. This option can be used to override --squash. </code> As in: <code> $ git checkout master $ git merge --squash <branch with many commits> $ git commit </code> ===== Setting merge options ===== ==== Per-branch merge options ==== From ''man git-config'', you can set (either locally or globally) //per-branch// merge options: <code> branch.<name>.mergeOptions Sets default options for merging into branch <name>. The syntax and supported options are the same as those of git- merge(1), but option values containing whitespace characters are currently not supported. </code> For example, if you wanted to prevent any fast-forward merges to any ''master'' branch across all of your repositories, you could: <code> $ git config --global branch.master.mergeOptions "--no-ff" </code> ==== Global merge.ff option ==== For merging, there is at least one repo-wide merge option you can set (see ''man git-merge''): <code> merge.ff By default, Git does not create an extra merge commit when merging a commit that is a descendant of the current commit. Instead, the tip of the current branch is fast-forwarded. When set to false, this variable tells Git to create an extra merge commit in such a case (equivalent to giving the --no-ff option from the command line). When set to only, only such fast-forward merges are allowed (equivalent to giving the --ff-only option from the command line). </code> So for widespread fast-forward merge configuration: <code> $ git config --global merge.ff "true" </code> This setting is superseded by any per-branch fast-forward merge setting. ===== Merge strategies ===== ==== ours ==== Technically record a merge while totally ignoring its content -- for record-keeping. Example: <code> $ git checkout master $ git merge --strategy=ours <obsolete branch> </code> How to make ''master'' look exactly like ''develop'': <code> $ git checkout topic $ git merge -s ours master $ git checkout master $ git merge --ff-only topic </code> To do this for an arbitrary commit, create a temporary branch: <code> $ git checkout -b tempbranch <commit ID> $ git merge -s ours master $ git checkout master $ git merge --ff-only tempbranch </code> git_merge.txt Last modified: 2019/03/13 13:09by rpjday