Git merge

Git Merge

Merging is Git's way of putting a forked history back together again. The git merge command lets you take the independent lines of development created by git branch and integrate them into a single branch.

Note that all of the commands presented below merge into the current branch. The current branch will be updated to reflect the merge, but the target branch will be completely unaffected. Again, this means that git merge is often used in conjunction with git checkout for selecting the current branch and git branch -d for deleting the obsolete target branch.

使用法

git merge <branch>

指定したブランチを現在のブランチにマージするコマンドです。Git では、マージアルゴリズムは自動的に選択されます (下で説明します)。

git merge --no-ff <branch>

Merge the specified branch into the current branch, but always generate a merge commit (even if it was a fast-forward merge). This is useful for documenting all merges that occur in your repository.

ディスカッション

独立したブランチにおけるフィーチャー開発作業が完了すると、それをメインコードベースに反映させる必要が生じます。Git では、これを行うに当たって、リポジトリの構成状態により複数の異なるアルゴリズム (早送りマージおよび三方向マージ) が用意されています。

A fast-forward merge can occur when there is a linear path from the current branch tip to the target branch. Instead of “actually” merging the branches, all Git has to do to integrate the histories is move (i.e., “fast forward”) the current branch tip up to the target branch tip. This effectively combines the histories, since all of the commits reachable from the target branch are now available through the current one. For example, a fast forward merge of some-feature into master would look something like the following:

Git チュートリアル: 早送りマージ

However, a fast-forward merge is not possible if the branches have diverged. When there is not a linear path to the target branch, Git has no choice but to combine them via a 3-way merge. 3-way merges use a dedicated commit to tie together the two histories. The nomenclature comes from the fact that Git uses three commits to generate the merge commit: the two branch tips and their common ancestor.

Git チュートリアル: 三方向マージ

While you can use either of these merge strategies, many developers like to use fast-forward merges (facilitated through rebasing) for small features or bug fixes, while reserving 3-way merges for the integration of longer-running features. In the latter case, the resulting merge commit serves as a symbolic joining of the two branches.

競合の解決

If the two branches you're trying to merge both changed the same part of the same file, Git won't be able to figure out which version to use. When such a situation occurs, it stops right before the merge commit so that you can resolve the conflicts manually.

The great part of Git's merging process is that it uses the familiar edit/stage/commit workflow to resolve merge conflicts. When you encounter a merge conflict, running the git status command shows you which files need to be resolved. For example, if both branches modified the same section of hello.py, you would see something like the following:

# On branch master # Unmerged paths: # (use "git add/rm ..." as appropriate to mark resolution) # # both modified: hello.py #

Then, you can go in and fix up the merge to your liking. When you're ready to finish the merge, all you have to do is run git add on the conflicted file(s) to tell Git they're resolved. Then, you run a normal git commit to generate the merge commit. It’s the exact same process as committing an ordinary snapshot, which means it’s easy for normal developers to manage their own merges.

なお、マージの際の競合が起こるのは三方向マージの場合のみであることに留意してください。早送りマージでは変更が競合を起こすことはありません。

早送りマージ

最初に早送りマージの例を示します。次のコードでは、新規ブランチを作成し、それに二つのコミットを加え、最後に早送りマージによってそれを master ブランチに統合しています。

# Start a new feature git checkout -b new-feature master # Edit some files git add <file> git commit -m "Start a feature" # Edit some files git add <file> git commit -m "Finish a feature" # Merge in the new-feature branch git checkout master git merge new-feature git branch -d new-feature

これは、(長期のフィーチャー開発を行なうための大規模組織向けのブランチではない) 独立した小規模開発に向けた短期間のフィーチャーブランチを用いる場合の一般的なワークフローです。

Also note that Git should not complain about the git branch -d, since new-feature is now accessible from the master branch.

三方向マージ

The next example is very similar, but requires a 3-way merge because master progresses while the feature is in-progress. This is a common scenario for large features or when several developers are working on a project simultaneously.

# Start a new feature git checkout -b new-feature master # Edit some files git add <file> git commit -m "Start a feature" # Edit some files git add <file> git commit -m "Finish a feature" # Develop the master branch git checkout master # Edit some files git add <file> git commit -m "Make some super-stable changes to master" # Merge in the new-feature branch git merge new-feature git branch -d new-feature

Note that it’s impossible for Git to perform a fast-forward merge, as there is no way to move master up to new-feature without backtracking.

For most workflows, new-feature would be a much larger feature that took a long time to develop, which would be why new commits would appear on master in the meantime. If your feature branch was actually as small as the one in the above example, you would probably be better off rebasing it onto master and doing a fast-forward merge. This prevents superfluous merge commits from cluttering up the project history.

Ready to learn Git?

Try this interactive tutorial.

今すぐ始める