20201016のGitに関する記事は11件です。

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-message

ex. ステージング・エリアに追加された style.css をリポジトリに記録

$ git commit -m "style.css added"
[master ecaefff] style.css added
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 style.css

config

設定内容の編集・確認

# ユーザ識別情報(ユーザ名とメールアドレス)を登録
git config --global user.name "【ユーザ名】"
git config --global user.email 【メールアドレス】

# ターミナルで出力する文字に色付けしたい場合
git config --global color.ui true

# 設定内容の確認
git config -l
git config --list

diff

変更されたファイルの差分を確認

# 変更されたファイルとステージング・エリア(git add 未実行の状態)の差分を確認
git diff

# ステージング・エリアとリポジトリ(git commit 未実行の状態)の差分を確認
git diff --cached

ex. 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 config

init

既存ディレクトリのリポジトリ初期化

# .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 --oneline

status

どのファイルがどの状態にあるのか確認

git status

ex. 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.html

ex. 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.css

ex. 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/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 master

origin の部分は、git remote addを実行する際に使用したリモート名

リモートのファイルをダウンロードする

ダウンロードすることを、プルという。

test $ git pull origin master

コミットログの確認

コミットメッセージのみ確認するコマンド

git log

変更内容も確認するコマンド

git log -p

表示内容が多い時は特殊な表示モードになる。
上下キーを使うと表示範囲を変えることができて、Qキーを押すと終了する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

自分用メモ 初心者の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 作成したブランチ名

スクリーンショット 2020-10-16 16.22.53.png
git hubのこの場所で確認できます。

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管理で最低限必要なものかなと思いました。
まだまだ学ぶべきものはあると思いますが、それはこれから深めていこうと思います。
記事についてですが、間違っている点などあれば教えていただけると幸いです。

参照

Git基本操作。ローカルでの作業からリモートリポジトリのマージまで。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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を復元すると、ファイルは削除されたままです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Git, GitHubの用語を整理する

Gitとは

ファイルのバージョンを管理するツール。
いつ、誰が、どのような変更を行ったのかを管理する。

GitHubとは

Gitで公開した他人の作品をブラウザで見ることのできるウェブサービス。

リポジトリ

ファイルや設定情報を保管する場所。

リモートリポジトリ

サーバーにあるリポジトリ。

ローカルリポジトリ

自分のPCにあるリポジトリ。

コミット

ファイルの追加や変更の履歴をローカルリポジトリに記録すること。

プッシュ

ローカルリポジトリの変更をリモートリポジトリに反映させること。

ブランチ

履歴管理を枝分かれさせてたもの。

クローン

リモートリポジトリをコピーしてローカルリポジトリを作成すること。

フェッチ

リモートリポジトリの変更をローカルリポジトリに持ってくる。

マージ

変更をローカルリポジトリに反映させること。

プル

リモートリポジトリの変更をローカルリポジトリに反映させること。
フェッチとマージをまとめてやってくれる。

プルリクエスト

自分が行った変更をオリジナルのものに反映させたいというときに使う通知。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

git reset [--soft | --mixed || --hard] まとめ

はじめに

git resetでは、コミットまたはファイルをリセットする使い方があります。
本記事では、コミットをリセットする際の使い方について解説していきます。

基本用語のおさらい

Gitでは、以下の3つの領域でファイルの編集履歴を管理しています。

  • ワークツリー
    現在編集している作業内容の状態を保存している領域。プロジェクトそのもの。
    ワーキングディレクトリ作業ツリーと呼ぶこともある。

  • インデックス
    コミットの前にgit addでワークツリーから移動させたファイルの状態を保存している領域。
    ステージングと言ったりする。

  • HEAD
    コミットしたファイルの状態を保存している領域。大雑把に説明すると、HEAD = 特定のコミットです。実際はもっと複雑です。HEADには、番号がついています。

構文

resetの構文
$ git reset [--soft || --mixed || --hard] [commit]

resetでは、softmixedhardの主に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からいくつ過去に遡るのかを指定します。HEADHEAD~0HEAD@{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についてまだまだ分からないことだらけなので、間違っているところがあれば、指摘してもらえると嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 stash

stash: 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/9565c6ad2ffc24c09364

push

git push

branch切った直後だと、親branchがわからないと言われるときもある。

git push --set-upstream origin {branch名}

とか出てきたらコピペして貼ってエンター。

*[new branch] {branch名} -> {branch名}

とか出たら、ブランチが増えたよ。
githubのリポジトリのページの「master」のところ押したら
新しくブランチ増えてるよ。
スクリーンショット 2020-10-16 11.34.51.png

「compare」押すと、
masterと比較して、どこを変更にしたか見れるよ。
スクリーンショット 2020-10-16 11.36.03.png

プルリク先を間違ったら

githubのプルリクページのeditから変えれるよ。
スクリーンショット 2020-10-16 21.56.32.png
※間違ってmasterとか選んじゃったら、ここからstagingとか選び直そう!



branchを削除する

例えば「develop」branchを削除する
deleteのD。

git branch -D develop

git log

今までの変更履歴のログを見る。
エンター押すと下に行く。

git log

cimmitの横に書いてあるのがcommitのID。
リバートとかリセットとかしだすと使う。

リバートとかリセットとかある

抜けたい時は

control + z
注意:「command」ボタンと間違えるので、「control」ボタンです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Git checkout無しでリモートブランチの名前を変更する方法

1.古いブランチから新しいブランチを作成する

git push origin origin/old_branch:refs/heads/new_branch

2.古いブランチを削除する

git push origin :old_branch

リモートブランチの名前が変更できたか確認するには以下のコマンドを使用する

git branch -r
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【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のファイルA
1|first commit
2|second commit
subのファイルA
1|first commit
2|sub first commit

この状態でmasterにsubをマージすると、コンフリクトが発生します。どちらを取り込むか聞かれるので、両方を取り込んでみます。non-fast-forwardなので、コミットメッセージをmergeにしてコミットしてみます。すると、以下のようになります。

masterにsubをマージした後のファイルA
1|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 commit

masterとsubがコミット名 = mergeでマージされ、コミットの履歴が枝分かれしています。
git logだとマージコミットの履歴は時系列順に統合されています。

また、コンフリクトではmasterとsubの共通部分のfirst commitの記述はそのまま、異なる部分はマージ元のmasterから先に取り込まれたことが分かりました。subにmasterをマージした場合は、コミット履歴は変わらず、subの記述から先に取り込まれます。

このように、non-fast-forwardのマージではブランチどうしの分岐が最終的に一点に集まるマージコミットが積まれ、双方のブランチの一番新しいコミットのファイルどうしを字句解析して比較し、一致しない部分があったらコンフリクトとして扱い、片方、もしくは両方を取り込むかを選択できます。

ちなみに、ファイルが完全一致していたらコンフリクトは発生しませんが、viエディタが開いてmergeの説明を求められます。

参考

いまさらだけどGitを基本から分かりやすくまとめてみた

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

振る舞いから理解するマージ、コンフリクトの仕組み

マージの種類

マージには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.txt
1|first commit
2|second commit
subのsample.txt
1|first commit
2|sub first commit

この状態でmasterにsubをマージすると、コンフリクトが発生します。どちらを取り込むか聞かれるので、両方を取り込んでみます。non-fast-forwardなので、コミットメッセージをmergeにしてコミットしてみます。すると、以下のようになります。

masterにsubをマージした後のsample.txt
1|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 commit

masterとsubがコミット名 = mergeでマージされ、コミットの履歴が枝分かれしています。
git logだとマージコミットの履歴は時系列順に統合されていますね。

また、コンフリクトではmasterとsubの共通部分のfirst commitの記述はそのまま、異なる部分はマージ元のmasterから先に取り込まれたことが分かりました。subにmasterをマージした場合は、コミット履歴は変わらず、subの記述から先に取り込まれます。

このように、non-fast-forwardのマージではブランチどうしの分岐が最終的に一点に集まるマージコミットが積まれ、双方のブランチの一番新しいコミットのファイルどうしを字句解析して比較し、一致しない部分があったらコンフリクトとして扱い、片方、もしくは両方を取り込むかを選択できます。

ちなみに、ファイルが完全一致していたらコンフリクトは発生しませんが、viエディタが開いてmergeの説明を求められます。

参考

いまさらだけどGitを基本から分かりやすくまとめてみた

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む