- 投稿日:2020-10-16T20:46:44+09:00
Gitコマンド
Git の基本
作業ディレクトリ: 実作業しているディレクトリ
↓
add
↓
ステージング・エリア: コミット対象のファイルが存在する仮想上の場所
↓
commit
↓
ローカルリポジトリ: 自分自身の作業環境でバージョン管理するために作成したリポジトリ
↓
push
↓
リモートリポジトリ: 複数人でバージョン管理・共有するために専用サーバに配置したリポジトリ※ リポジトリ・・・ファイルやディレクトリの状態を記録する場所
add
ファイルをステージング・エリアに追加
git add 【ファイル名】 # 変更された全ファイルをステージング・エリアに追加 git add -A git add --all # カレントディレクトリ以下の、変更された全ファイルをステージング・エリアに追加 git add . # バージョン管理されており、変更された全ファイルをステージング・エリアに追加 git add -u git add --update
New Files Modified Files Deleted Files git add -A 〇 〇 〇 git add . 〇 〇 〇 git add -u × 〇 〇 【参考】
git add -u と git add -A と git add . の違いcommit
ステージング・エリアの状態をリポジトリに記録
# コミットメッセージを指定 git commit -m "【メッセージ】" git commit --message="【メッセージ】" # 直前のコミットメッセージを修正 git commit --amend # メッセージを指定しないコミットを許可 git commit -m --allow-empty-messageex. ステージング・エリアに追加された style.css をリポジトリに記録
$ git commit -m "style.css added" [master ecaefff] style.css added 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 style.cssconfig
設定内容の編集・確認
# ユーザ識別情報(ユーザ名とメールアドレス)を登録 git config --global user.name "【ユーザ名】" git config --global user.email 【メールアドレス】 # ターミナルで出力する文字に色付けしたい場合 git config --global color.ui true # 設定内容の確認 git config -l git config --listdiff
変更されたファイルの差分を確認
# 変更されたファイルとステージング・エリア(git add 未実行の状態)の差分を確認 git diff # ステージング・エリアとリポジトリ(git commit 未実行の状態)の差分を確認 git diff --cachedex. index.html を変更し、git add 実行後に差分を確認
$ git diff --cached diff --git a/index.html b/index.html index 732c3b4..e967372 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ - (マイナス) が削除された行 ※通常は赤で表示 + (プラス) が追加された行 ※通常は緑で表示help
ヘルプの参照
git help 【コマンド】 git 【コマンド】 --help man git-【コマンド】 # ex. config コマンドのヘルプを参照する git help configinit
既存ディレクトリのリポジトリ初期化
# .git という名前の新しいサブディレクトリが作られ、リポジトリに必要なすべてのファイルがその中に格納される git init # ex. /home ディレクトリに空のリポジトリを作成 $ cd /home $ git init Initialized empty Git repository in /home/.git/log
コミット履歴の閲覧
# すべてのコミットログを表示 git log # 最新のコミットログを1件のみ表示 git log -1 # すべてのコミットログを1行で簡潔に表示 git log --onelinestatus
どのファイルがどの状態にあるのか確認
git statusex. index.html が更新されているが、ステージング・エリアに追加されていない
(git add も git commit も未実行の状態)$ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.htmlex. style.css がステージング・エリアには登録されているが、リポジトリには記録されいない
(git add は実行済だが、git commit が未実行の状態)$ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: style.cssex. script.js が作成されているが、ステージング・エリアに追加されていない
(新規作成されたファイルが git add も git commit も未実行の状態)$ git status Untracked files: (use "git add <file>..." to include in what will be committed) script.js【参考】
https://git-scm.com/book/ja/
https://backlog.com/ja/git-tutorial/
- 投稿日:2020-10-16T17:45:41+09:00
Gitの基本的なコマンドのまとめ
いつかGitを使って開発行うこともあるかもしれないと思い、
とりあえず基本的な部分をメモとして残すことに。Gitとは?
分散型バージョン管理システムのこと。
ちなみにGitHubは、Gitを使ったソフトウェア開発PJのための共有ウェブサービスのこと。GitとSubversionの違い
- Git
- 同じ情報を持つリポジトリを、開発者ごとに持つことができる(分散型)
- ローカルで
- 間違ってコミットしてしまったソース等が、いきなりメンバーに共有されて影響を与える心配がない。
- SVNと比べて操作がやや難しい部分がある。
- SVN
- 開発者全員が共有するリポジトリに対して修正内容を反映(集中型)
- 操作が簡単なので、初心者でも扱いやすい。
- 他の人との競合や、間違って不完全なソースコードを共有してしまう危険がある。
Gitでよく使う用語
用語 内容 リポジトリ
(repository)ソースコードや修正履歴、コメント等を保存している場所。 リモートリポジトリ
(remote repository)サーバに保存されていて、複数人で共有するためのリポジトリ。 ローカルリポジトリ
(local repository)ローカルに保存されているリポジトリ。 クローン
(clone)リモートリポジトリのファイルや変更履歴を丸ごと複製(ダウンロード)すること。 ブランチ
(branch)一連の修正を、いくつかに分岐させて管理するもの。
ブランチでの修正内容は他のブランチの影響を受けないため、同じリポジトリで同時に複数の変更を行うことができる。チェックアウト
(checkout)他のブランチへ移動し、作業ディレクトリを任意のコミット状態にすること。 コミット
(commit)修正内容をローカルリポジトリに反映すること。 プッシュ
(push)ローカルリポジトリの修正内容をリモートリポジトリに反映すること。 プル
(pull)リモートリポジトリの修正内容をローカルリポジトリに反映すること。
※ローカルリポジトリとの差分のみをダウンロードして更新する。マージ
(merge)異なるブランチの修正内容を反映すること。
マージ先とマージ元の両方に変更履歴が残る。コンフリクト
(conflict)マージの際に、リモートとローカルで同じファイルの同じ箇所に対して修正がされており、自動でマージできないこと。
両方の修正を合わせた内容に手動で編集する必要がある。Gitを使う準備
新しいリポジトリを作成するコマンド
test $ git init共有するファイルの選択
共有したいファイルを作成する(ex:index.html)
test $ git add index.html(共有したいファイル名)変更したファイルを把握する
下記コマンドによって、自分がどのファイルを変更したか確認できる。
test $ git status On branch masterChanges not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.html modified: stylesheet.css no changes added to commit (use "git add" and/or "git commit -a")変更した内容を把握する
コードを変更した部分は、
変更前のコード:赤色で表示される。
変更後のコード:緑色で表示される。内容に問題がなければ、git addを実行する
addしたファイルを確認する
どのファイルをaddして、どのファイルをaddしていないかを確認ができるのは、
先ほども使用したコマンド「git status」を実行することで確認できる。addされたファイル :緑色の文字で表示される。
addされていないファイル:赤色の文字で表示される。ファイルの記録
いわゆる コミット のこと
test $ git commit -m "Create index.html"コミットメッセージは分かりやすく書く
コミットする際に、メッセージを適当にするとどんな修正を行ったのか分かりずらくなる。
なるべく具体的に、簡潔に書くように気を付ける。共有の仕組み
Gitでは「リモート」という共有ファイルの置き場を使用する。
リモートファイルにアップロードしたり、
リモートからファイルをダウンロードすることで、
開発者同士がファイルを共有することができる。リモートの準備
リモートにアップロードするためには、そのリモートのURLを登録する必要がある。
リモートを登録する際には名前を付ける必要があり、基本的に「origin」とすることが多いらしい。test $ git remote add リモート名 リモートのURLリモートの名前を変更する
リモートの名前を変更したい場合は下記コマンドを実行すると、変更できる。
git remote rename 古いリモート名 新しいリモート名リモートにファイルをアップロードする
アップロードすることを、プッシュという。
test $ git push origin masterorigin の部分は、git remote addを実行する際に使用したリモート名
リモートのファイルをダウンロードする
ダウンロードすることを、プルという。
test $ git pull origin masterコミットログの確認
コミットメッセージのみ確認するコマンド
git log変更内容も確認するコマンド
git log -p表示内容が多い時は特殊な表示モードになる。
上下キーを使うと表示範囲を変えることができて、Qキーを押すと終了する。
- 投稿日:2020-10-16T16:40:05+09:00
自分用メモ 初心者のgit
はじめに
私自身大学卒業後はフロントエンドエンジニアとして働いていこうと考えております。そのためにもチーム開発では必須であるgitがどのようなものであるかは最低限、理解しておかなければなりません。
もちろんチーム開発をすることがgit理解の1番の近道だとは思いますが、現段階では、どのようなものか理解し、自分が作成したものをgit hub上で公開、管理できるようになっていれば最低限、いいのかなと考えております。この記事では、ローカルファイルからのリモートへpush方法、変更の方法を載せていきたいと思います。
そのため私と同様の初心者の方向けの記事になるかと思います。
至らない点などあると思いますが、その時は、教えていただけると幸いです。Gitとは
Gitとは、分散型バージョン管理システム
簡単にいうとファイルの状態(バージョン)を保持し、元の状態へ戻したり、更新したり、することのできるツール。
ひとつひとつコードの編集の度に古いバージョンの日付や時刻ををつけて保存して、また新しい作業をするようなことをしていては、時間はかかりますし、人的ミスも増えることは、いうまでもありません。そういった作業を無駄なく、効率的に行うためのツールがGitこれができると複数人で管理するときにとても便利!!
git hub
git hubは、gitを使った開発者向けのwebサービス。
クラウド上にリモートリポジトリを提供することで、遠く離れた開発者同士でもソースコードを管理できるツールorigin リモートリポジトリ(git hub)の別名
master デフォルトのブランチの名前。メインになる。git initしたときのデフォルトで入る名前基本的なコマンド
git init //git管理するリポジトリを作成するときに利用(一番最初) git add //バージョン管理対象へ追加 ステージング git commit -m 'commit message' //ファイルやディレクトリの追加・変更をリポジトリに記録 git clone //リモートリポジトリからのコピー git push //コミットをリモートリポジトリに追加 git pull //変更されたリモートリポジトリをローカルへ取り込む git status //ステージング、管理対象のファイルの一覧 git checkout //ブランチの切り替え コミットの移動でも、、、 git branch //ブランチ一覧 git log //コミット履歴 git merge //変更をマージさせるgithub(リモートリポジトリ)変更、更新方法
1.ブランチ作成
git checkout -b 作成するブランチ名
Switched to a new branch ブランチ名と出たら成功です!
git branch -a でブランチの一覧を確認してみていください!!
2.作成したブランチをリモートに登録
git push -u origin 作成したブランチ名
3.git add で変更点の追加
git add 追加したいファイル、ディレクトリ
オプションでadd .とするとカレントの変更点全てをaddできる
4.git commitでファイルをコミット
git commit -m 'コミットメッセージ'
git logでコミットを確認できる!
5.ファイルをpush
git push
これでgit hubの追加したブランチのソースコードが更新されています。
6.マージする
git checkout master
masterブランチに切り替える
git merge ブランチ名
これでmasterブランチが先ほどのブランチとmergeされ更新される
7.git hubのリポジトリに反映
git push origin master
これでgit hub上に変更を更新できる。
最後に作ったブランチを削除
git branch --delete ブランチ名
最後に
この流れが初心者ののgit管理で最低限必要なものかなと思いました。
まだまだ学ぶべきものはあると思いますが、それはこれから深めていこうと思います。
記事についてですが、間違っている点などあれば教えていただけると幸いです。参照
- 投稿日:2020-10-16T16:35:38+09:00
git stashまとめ
stashってなに?
現在編集中のワークツリー、インデックスのファイルの状態を一時的に保管させておくことができる場所。
「ブランチを切り替えたいけど今はコミットしたくない」といった場合に、今作業している内容を一旦保存して、ブランチを綺麗にすることができる。stashに保存したファイルは、あとで自由に復元することができる。
stashで使えるコマンド
save
$ git stash [save ['message']]現在の作業の編集内容をstashに保存します。
save
を省略した場合、デフォルトでgit stash
になります。
save
を省略しなかった場合は、さらにstashの内容を示すメッセージを残すことができます。apply
$ git stash apply [stash@{n}]stashに保存した作業内容を復元します。
pop
と違い、復元した後でもstashが破棄されません。
引数には、復元したいstashを指定することができます。引数を省略した場合はデフォルトでstash@{0}
が指定されるので、最新のstashが復元されます。pop
$ git stash pop [stash@{n}]指定したstashを復元します。
apply
とは違い、復元したstashは破棄されます。
apply
同様、引数を省略した場合はデフォルトでstash@{0}
が選択されます。show
$ git stash show [stash@{n}]指定したstashの内容を確認します。
引数は前項と同じです。list
$ git stash list現在保存されているstashをリストで確認します。stashの番号は、こちらで確認することができます。
drop
$ git stash drop [stash@{n}]指定したstashを破棄します。引数を省略した場合のデフォルトは
stash@{0}
です。clear
$ git stash clear現在のstashを全て破棄します。
stash復元の挙動について
あまり実用的ではないものもありますが、各ケースにおけるstash復元の動きについてのまとめです。
以下の3つのケースで、挙動が異なります。現在のHEADのファイルがstashされたときのHEADと全く同じ場合
stashは正常に復元される。一致するのはファイルだけでいいので、別のコミットを積んでいても復元できる。
現在のHEADのファイルがstashされたときのHEADと異なる場合
コンフリクト
が発生する。コンフリクトでは、どちらのファイルを取り込むか聞かれる。コンフリクト解消後、コミットをしてもマージコミット
は積まれない。現在のHEADのファイルが復元後のstashと全く同じ内容の場合
何も起こらない。この状態でファイルを削除してからstashを復元すると、ファイルは削除されたままです。
- 投稿日:2020-10-16T15:11:12+09:00
Git, GitHubの用語を整理する
Gitとは
ファイルのバージョンを管理するツール。
いつ、誰が、どのような変更を行ったのかを管理する。GitHubとは
Gitで公開した他人の作品をブラウザで見ることのできるウェブサービス。
リポジトリ
ファイルや設定情報を保管する場所。
リモートリポジトリ
サーバーにあるリポジトリ。
ローカルリポジトリ
自分のPCにあるリポジトリ。
コミット
ファイルの追加や変更の履歴をローカルリポジトリに記録すること。
プッシュ
ローカルリポジトリの変更をリモートリポジトリに反映させること。
ブランチ
履歴管理を枝分かれさせてたもの。
クローン
リモートリポジトリをコピーしてローカルリポジトリを作成すること。
フェッチ
リモートリポジトリの変更をローカルリポジトリに持ってくる。
マージ
変更をローカルリポジトリに反映させること。
プル
リモートリポジトリの変更をローカルリポジトリに反映させること。
フェッチとマージをまとめてやってくれる。プルリクエスト
自分が行った変更をオリジナルのものに反映させたいというときに使う通知。
- 投稿日:2020-10-16T14:13:00+09:00
git reset [--soft | --mixed || --hard] まとめ
はじめに
git reset
では、コミットまたはファイルをリセットする使い方があります。
本記事では、コミットをリセットする際の使い方について解説していきます。基本用語のおさらい
Gitでは、以下の3つの領域でファイルの編集履歴を管理しています。
ワークツリー
現在編集している作業内容の状態を保存している領域。プロジェクトそのもの。
ワーキングディレクトリ
、作業ツリー
と呼ぶこともある。
インデックス
コミットの前にgit add
でワークツリーから移動させたファイルの状態を保存している領域。
ステージング
と言ったりする。
HEAD
コミットしたファイルの状態を保存している領域。大雑把に説明すると、HEAD = 特定のコミットです。実際はもっと複雑です。HEADには、番号がついています。構文
resetの構文$ git reset [--soft || --mixed || --hard] [commit]
reset
では、soft
、mixed
、hard
の主に3つのオプションがあります。
このオプションは省略することもできます。
commit
には、HEAD
もしくはコミットID
を直接指定します。いずれのオプションでも共通するのは、HEADを指定したコミットまでリセットするということです。リセット地点までのコミット履歴は、破棄されます。
例えば、A→B→C→Dと積まれたコミット履歴があるとします。現在のHEADはDです。この状況でコミット履歴をBまでリセットすると、HEADはBに移動します。
では、この3つのオプションで他にどんな違いがあるのかというと、ワーキングディレクトリとインデックスの挙動があります。
soft
HEADだけを指定したコミット地点までリセットします。ワークツリーとインデックスは現在の内容を保持します。そのため、現在の内容のまま過去のコミット履歴に戻って、新しいコミットの歴史を作ることができます。
mixed
HEADに加えて、インデックスもリセットします。ワークツリーはsoft同様に現在の状態を保持したままです。そのため、リセット前の内容は、ステージングされていない変更点として扱われます。オプションを省略した場合のデフォルトの挙動がmixed
になります。
hard
HEAD、ワークツリー、インデックスを全て指定したコミットまでリセットします。とても便利なオプションですが、基本的には復元が効かないので、使うときは慎重になりましょう。実際の活用例
- 現在のステージングだけを取り消したい
$ git reset {--mixed} HEAD現在の
add
を取り消したい場合に使えるコマンドがこちらです。
git reset HEAD
としてすでに使っている方も多いのではないでしょうか?これは、デフォルトの引数mixed
が省略された形です。mixed
の性質上、ワークツリーは今のまま、最新のHEADを復元し、add
を取り消しているために、結果的にステージングだけを取り消すことができます。
- 今の内容のまま過去のコミットに戻って歴史を書き換えたい
$ git reset --soft HEAD^ $ git add . $ git commit -m 'something'
soft
で、現在の内容をキープしたまま、過去に戻ってコミットし直すことができます。HEAD^
とすることで、直前のHEADを指定することができます。
- 過去のコミットを復元する
$ git reset --hard HEAD~n
マージコミット
を含めた同じブランチ内でのHEADの移動は、HEAD~n
で指定することができます。nには現在のHEADからいくつ過去に遡るのかを指定します。HEAD
、HEAD~0
、HEAD@{0}
はいずれも現在のHEADです。
- コミット履歴に存在しない昔のコミットに戻る
hard
の説明で、基本的にはコミットの復元がきかないと解説しました。ですが、git reflog
を使うことで、git log
では確認することのできない他のブランチのコミットや、リセットで消失したコミットの履歴なども、閲覧することができます。//HEADの番号 or コミットIDを確認 $ git reflog 57709fd HEAD@{0}: //行った操作の説明 a87bfaa HEAD@{1}: 9a29da6 HEAD@{2}: //9a29da6まで戻る $ git reset --hard HEAD@{2}
コミットID
またはHEAD@{n}
の形式で指定する際の特徴は、過去にHEADが辿ったあらゆるコミットに移動できるという点です。サブブランチ
やマージコミット
に飛ぶことすらできます。fast-forward
マージになる場合は、直接マージするサブブランチのコミットに飛ぶことで、実質的にマージしたような状態になります(おすすめはしません)。※
fast-forward
マージの解説はこちらでしています。
【Git】振る舞いから理解するマージ、コンフリクトの仕組み終わりに
筆者は、
git reset
を使えるようになったことでgitの操作が格段に捗るようになりました。とても便利なコマンドなので、この記事を見て、ぜひ参考にしてもらえると嬉しいです。また、私自身もgitについてまだまだ分からないことだらけなので、間違っているところがあれば、指摘してもらえると嬉しいです。
- 投稿日:2020-10-16T11:43:20+09:00
gitコマンドメモ
gitコマンドメモ
自分用です。(簡易メモです。すみません。)
@horri1520 くんがとても丁寧に教えてくれました。
いつもありがとう。?リポジトリのクローン
git clone {リポジトリクローンするときのURL}「クローン」のボタン押してSSHかHTTPSか選べるやつをどっちか貼る。
(SSHキーの設定の関係で、うまくいったりいかなかったりする。)feature branchで作業
feature/#{Issue Number}_describe_issue参考:Git-flowって何?
https://qiita.com/KosukeSone/items/514dd24828b485c69a05新しいbranchを作って移動
「-c」は「create」のc。
git switch -c "feature/#164_implement_contact_page_for_mobile"結果↓
Switched to a new branch 'feature/#164_implement_contact_page_for_mobile'
branch作るの忘れてた時
stash: 変更点を別の場所に一旦退避させたい時。
git stashstash: stashさせてたのを戻す
git stash pop
add
変更したものを全部stageに追加
git add .「.」は全部stageに追加する
git add .eslintrc特定のファイルのパス(上は「.eslintrc」のファイルをaddしたかったとき)
とかgit add .eslintrc -p特定のファイルの、行単位でのcommit(上は「.eslintrc」のファイルの中の行単位でcommitするか決めれる)
とかもあるよ。hunkっていうまとまり単位でcommitしますか?ってきかれるので[y,n]で追加するかを決めれる。
コミットメッセージ
例えば
git commit -m '[add] create form'とか
git commit -m '[fix] css fix'とか
git commit -m '[upgrade] eslint version setting'とか
[add] 新規(ファイル)機能追加
[fix] バグ修正
[hotfix] クリティカルなバグ修正
[update] 機能修正(バグではない)
[change] 仕様変更
[clean] 整理(リファクタリング等)
[disable] 無効化(コメントアウト等)
[remove] 削除(ファイル)
[upgrade] バージョンアップ
[revert] 変更取り消し参考:Gitのコミットメッセージの書き方
https://qiita.com/itosho/items/9565c6ad2ffc24c09364push
git pushbranch切った直後だと、親branchがわからないと言われるときもある。
git push --set-upstream origin {branch名}とか出てきたらコピペして貼ってエンター。
*[new branch] {branch名} -> {branch名}とか出たら、ブランチが増えたよ。
githubのリポジトリのページの「master」のところ押したら
新しくブランチ増えてるよ。
「compare」押すと、
masterと比較して、どこを変更にしたか見れるよ。
プルリク先を間違ったら
githubのプルリクページのeditから変えれるよ。
※間違ってmaster
とか選んじゃったら、ここからstaging
とか選び直そう!
branchを削除する
例えば「develop」branchを削除する
deleteのD。git branch -D developgit log
今までの変更履歴のログを見る。
エンター押すと下に行く。git logcimmitの横に書いてあるのがcommitのID。
リバートとかリセットとかしだすと使う。他
リバートとかリセットとかある
抜けたい時は
control + z
注意:「command」ボタンと間違えるので、「control」ボタンです。
- 投稿日:2020-10-16T09:02:59+09:00
Git checkout無しでリモートブランチの名前を変更する方法
- 投稿日:2020-10-16T05:21:30+09:00
Gitリポジトリの移行
オンプレミスのGitリポジトリを、クラウド上のGit (例えば CodeCommit ) に移行したいケースを考えてみます。
Cloning
オンプレミスのGitリポジトリの全履歴をクローンするために、
--mirror
オプションをつけて実行します。$ git clone --mirror <Git Repository URL>クローンすると、
<Repository Name>.git
ディレクトリが作成されます。
このディレクトリ名が、example.git
だと仮定して次に進みます。移行Push
移行先のGitリポジトリにPushします。
$ cd example.git $ git push --mirror <移行先 Git Repository URL>
- 投稿日:2020-10-16T00:28:11+09:00
【Git】振る舞いから理解するマージ、コンフリクトの仕組み
マージの種類
マージには2種類の処理の仕方があります。
fast-forward
: 派生元のブランチがマージするブランチの作成時と比べて進んでいないときの処理。
non-fast-forward
: 派生元のブランチがブランチ作成時と比べて進んでいるときの処理。
fast-forward
では、コンフリクトが発生しません。マージした後、コミット履歴はそのまま結合されるので、新たにコミットをする必要はありません。一方で、
non-fast-forward
ではコンフリクトが発生することがあります。コンフリクトを解消した後、新たにマージコミット
を積む必要があります。マージコミットは両ブランチのコミットを作成したときの時系列順に積まれますが、reset
でマージ前に戻すと元に戻ります。コンフリクトでは、どちらのブランチを取り込むか選択します。片方だけを取り込んだ場合は、選択したブランチの内容が反映されます。両方を取り込んだ場合は、ファイルに差異がある部分だけをマージ元のブランチから先に追記していきます。
振る舞いを確認してみる
【fast-forward】
以下のような操作を行います。
1.masterでsample.txtを作成
2.masterをsubブランチにコピー
3.subでsub.txtを作成
4.masterでsubをマージfast-forwardのマージ// masterにsample.txtを作成 $ touch sample.txt $ git add . $ git commit -m 'first commit' // masterをsubにコピーし、sub.txtを作成 $ git checkout -b sub $ touch sub.txt $ git add . $ git commit -m 'add sub.txt' // masterにsubをマージ $ git checkout master $ git merge sub Fast-forward $ git log add sub.txt first commitこのように、fast-forwardではマージ元のHEADをマージするサブブランチの先頭まで持ってくればいいだけなので、コンフリクトは一切発生しません。
【non-fast-forward】
以下のような手順でmasterとsubブランチを作ります。
1.masterでsample.txtの1行目にfirst commitを追記してコミット
2.masterをsubブランチにコピー
3.subでsample.txtの2行目にsub first commitを追記してコミット
4.masterで2行目にsecond commitを追記してコミットnon-fast-forwardの例//masterでsample.txtにfirst commitを記述 $ touch sample.txt && echo "first commit" >> sample.txt $ git add . $ git commit -m 'first commit' //subでsub first commitを追記 $ git checkout -b sub $ echo "sub first commit" >> sample.txt $ git add . $ git commit -m 'sub first commit' //masterでsecond commitを追記 $ git checkout master $ echo "second commit" >> sample.txt $ git add . $ git commit -m 'second commit'すると、以下のような状態になります。
masterのファイルA1|first commit 2|second commitsubのファイルA1|first commit 2|sub first commitこの状態でmasterにsubをマージすると、コンフリクトが発生します。どちらを取り込むか聞かれるので、両方を取り込んでみます。
non-fast-forward
なので、コミットメッセージをmergeにしてコミットしてみます。すると、以下のようになります。masterにsubをマージした後のファイルA1|first commit 2|second commit 3|sub first commitコミット履歴$ git log merge second commit sub first commit first commitブランチの分岐$ git log --graph * commit 2e4930ad822957bf80f80bf3cdfa43f603e9967c (HEAD -> master) |\ Merge: c5d1dd2 4d79fe0 | | Author: | | Date: Fri Oct 16 01:07:07 2020 +0900 | | | | merge | | | * commit 4d79fe011d927d2c0dc3bf9dc517e001b7d602e7 (sub) | | Author: | | Date: Fri Oct 16 01:05:47 2020 +0900 | | | | sub first commit | | * | commit c5d1dd2917cd655cf0605bb3b3ad9e1b60f19927 |/ Author: | Date: Fri Oct 16 01:06:19 2020 +0900 | | second commit | * commit eec69490976f4d67241801d2f6fb8b1ee6f4d001 Author: Date: Fri Oct 16 01:05:10 2020 +0900 first commitmasterとsubがコミット名 = mergeでマージされ、コミットの履歴が枝分かれしています。
git logだとマージコミットの履歴は時系列順に統合されています。また、コンフリクトではmasterとsubの共通部分の
first commit
の記述はそのまま、異なる部分はマージ元のmasterから先に取り込まれたことが分かりました。subにmasterをマージした場合は、コミット履歴は変わらず、subの記述から先に取り込まれます。このように、
non-fast-forward
のマージではブランチどうしの分岐が最終的に一点に集まるマージコミット
が積まれ、双方のブランチの一番新しいコミットのファイルどうしを字句解析して比較し、一致しない部分があったらコンフリクトとして扱い、片方、もしくは両方を取り込むかを選択できます。ちなみに、ファイルが完全一致していたらコンフリクトは発生しませんが、viエディタが開いてmergeの説明を求められます。
参考
- 投稿日:2020-10-16T00:28:11+09:00
振る舞いから理解するマージ、コンフリクトの仕組み
マージの種類
マージには2種類の処理の仕方があります。
fast-forward
派生元のブランチがマージするブランチの作成時と比べて進んでいないときの処理。
fast-forward
では、コンフリクトが発生しません。マージした後、コミット履歴はそのまま結合されるので、新たにコミットをする必要はありません。non-fast-forward
派生元のブランチがブランチ作成時と比べて進んでいるときの処理。
non-fast-forward
ではコンフリクトが発生することがあります。コンフリクトを解消した後、新たにマージコミット
を積む必要があります。コンフリクトでは、どちらのブランチを取り込むか選択します。片方だけを取り込んだ場合は、選択したブランチの内容が反映されます。両方を取り込んだ場合は、ファイルに差異がある部分だけをマージ元のブランチから先に追記していきます。
振る舞いを確認してみる
fast-forwardの例
以下のような操作を行います。
1.masterでsample.txtを作成
2.masterをsubブランチにコピー
3.subでsub.txtを作成
4.masterでsubをマージfast-forwardのマージ// masterにsample.txtを作成 $ touch sample.txt $ git add . $ git commit -m 'first commit' // masterをsubにコピーし、sub.txtを作成 $ git checkout -b sub $ touch sub.txt $ git add . $ git commit -m 'add sub.txt' // masterにsubをマージ $ git checkout master $ git merge sub Fast-forward $ git log add sub.txt first commitこのように、fast-forwardではマージ元のHEADをマージするサブブランチの先頭まで持ってくればいいだけなので、コンフリクトは一切発生しません。
non-fast-forwardの例
以下のような手順でmasterとsubブランチを作ります。
1.masterでsample.txtの1行目にfirst commitを追記してコミット
2.masterをsubブランチにコピー
3.subでsample.txtの2行目にsub first commitを追記してコミット
4.masterで2行目にsecond commitを追記してコミットnon-fast-forwardの例//masterでsample.txtにfirst commitを記述 $ touch sample.txt && echo "first commit" >> sample.txt $ git add . $ git commit -m 'first commit' //subでsub first commitを追記 $ git checkout -b sub $ echo "sub first commit" >> sample.txt $ git add . $ git commit -m 'sub first commit' //masterでsecond commitを追記 $ git checkout master $ echo "second commit" >> sample.txt $ git add . $ git commit -m 'second commit'すると、以下のような状態になります。
masterのsample.txt1|first commit 2|second commitsubのsample.txt1|first commit 2|sub first commitこの状態でmasterにsubをマージすると、コンフリクトが発生します。どちらを取り込むか聞かれるので、両方を取り込んでみます。
non-fast-forward
なので、コミットメッセージをmergeにしてコミットしてみます。すると、以下のようになります。masterにsubをマージした後のsample.txt1|first commit 2|second commit 3|sub first commitコミット履歴$ git log merge second commit sub first commit first commitブランチの分岐$ git log --graph * commit 2e4930ad822957bf80f80bf3cdfa43f603e9967c (HEAD -> master) |\ Merge: c5d1dd2 4d79fe0 | | Author: | | Date: Fri Oct 16 01:07:07 2020 +0900 | | | | merge | | | * commit 4d79fe011d927d2c0dc3bf9dc517e001b7d602e7 (sub) | | Author: | | Date: Fri Oct 16 01:05:47 2020 +0900 | | | | sub first commit | | * | commit c5d1dd2917cd655cf0605bb3b3ad9e1b60f19927 |/ Author: | Date: Fri Oct 16 01:06:19 2020 +0900 | | second commit | * commit eec69490976f4d67241801d2f6fb8b1ee6f4d001 Author: Date: Fri Oct 16 01:05:10 2020 +0900 first commitmasterとsubがコミット名 = mergeでマージされ、コミットの履歴が枝分かれしています。
git logだとマージコミットの履歴は時系列順に統合されていますね。また、コンフリクトではmasterとsubの共通部分の
first commit
の記述はそのまま、異なる部分はマージ元のmasterから先に取り込まれたことが分かりました。subにmasterをマージした場合は、コミット履歴は変わらず、subの記述から先に取り込まれます。このように、
non-fast-forward
のマージではブランチどうしの分岐が最終的に一点に集まるマージコミット
が積まれ、双方のブランチの一番新しいコミットのファイルどうしを字句解析して比較し、一致しない部分があったらコンフリクトとして扱い、片方、もしくは両方を取り込むかを選択できます。ちなみに、ファイルが完全一致していたらコンフリクトは発生しませんが、viエディタが開いてmergeの説明を求められます。
参考