コンテンツにスキップ

Git基本操作

gistから引っ越し。

git clone

branchを指定

$ git clone -b <branch-name> <repository-URL>

tagの場合も同じように

$ git clone -b <tag-name> <repository>

出力先ディレクトリ指定

-l <dirname>を付ける

$ git clone -b <branch-name> <repository-URL> -l app-src-work

実は-lは無くてもよい。

$ git clone <repository-url> <local-path>

ローカルリポジトリ作成

リポジトリ用ディレクトリを作ってそのディレクトリ上でgit initしてREADME.mdをinitial commitする。

$ git init
$ echo "# this is hogehgoe repository" >> README.md
$ git add README.md
$ git commit -m "first commit"

リモートリポジトリ作成

ssh

$ cd /opt/repos
$ git init --bare sample.git

これで /opt/repos/sample.git リポジトリが出来る。

$ cd ${workdir}
$ git clone ssh://localhost/opt/repos/sample.git

これでワークディレクトリにcloneできる。
この場合対象の書き込み権限は必要。

このgit init --bare <path>git cloneしたクローンしたリポジトリにも有効。

commit

まず対象をadd

$ git add path/file

commit

$ git commit

これ実行するとエディタが起動する。 先頭#になってる行は全て無視されるので、任意の位置にコミットログを入力する

optionでコミットメッセージ付きcommit

$ git commit -m "commit messages"

amend

$ git commit --amend

直前のコミットに内容をあとから追加できる。
コミット漏れのファイルがあった場合などに1コミットにまとめられる。

$ git commit --amend --no-edit

--no-editを付与すれば、コミットログは前と同じものを使用できる。

マージ

hogehogeブランチをマージする

$ git merge hogehoge

マージコミットを作る (--no-ff)

$ git merge features/add_worker_node --no-ff 

rebaseでマージ

作業ブランチをmasterにmergeする前に、masterの変更点を作業ブランチでrebaseで取り込んでおく、が基本の使用法っぽい。

mergeは「他ブランチの内容を取り込む」で、rebaseは「他ブランチの内容を適用済みだったことにする」かな?

リモートブランチから最新を取得

$ git fetch origin 

指定ブランチの内容をrebaseで現在のブランチへ取り込み

$ git rebase origin/hogehoge

変更がローカルに残ってる場合は

$ git rebase origin/hogehoge
error: cannot rebase: You have unstaged changes.
error: Please commit or stash them.

エラーになるので、退避してrebaseする

$ git stash save
$ git rebase origin/hogehoge
$ git stash pop

origin/mainから取り込むときにpullするとmergeになってしまうので、rebaseしたい場合はfetchする。(たぶん)

conflictした場合

修正する場合は普通に

  1. 修正する
  2. addしてcommitする(普通)

(「修正する」をもう少し詳しくあとで書こう)

mergeをやめる場合(未修正)

$ git merge --abort

マージ前の状態に戻る

stash pop後のconflict

メッセージが以下のようになりgit merge --abortは効かない。
状態としてはステージングになっている。

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
        both modified:   filename

メッセージにある通り、コンフリクトを解決したのであればgit addを、変更を破棄したい場合はgit restore --stagedaddを取り消し、さらにgit restoreすれば変更前の状態に戻る。

add (ステージング)

ステージングに追加

$ git add <path>

パスはディレクトリ指定の場合は再帰的にファイルが追加される

行単位のadd

$ git add -p

実行するとdiffが表示されるので、変更単位ごとにyで追加・nでスルーできる。
変更単位を細かく分割する場合はeでエディタが起動するので、

  • -の削除行を対象外にするにはスペースに変更
  • +の追加行を対象外にするには行削除

する。

To remove '-' lines, make them ' ' lines (context). To remove '+' lines, delete them. Lines starting with # will be removed. If the patch applies cleanly, the edited hunk will immediately be marked for staging. If it does not apply cleanly, you will be given an opportunity to

追加の取り消し

$ git reset HEAD <path>

ステージングのファイルの確認

$ git status

ステージングに追加された差分を確認

$ git diff --cached [file]

ブランチ操作

今いるブランチどこ?

$ git branch 
  dev/calico
  devel
  features/cni_use_calico
  features/delete_node
  features/divide_playbook
  features/divide_roles
  features/separate_cni_firewalld_configure
  features/separate_parameters
  features/wait_new_node
* master

ブランチ作成

$ git branch features/divide_playbook

ブランチ切り替え

$ git checkout features/divide_playbook

Git 2.23以降は

$ git switch features/divide_playbook

ブランチ作成&切り替え

$ git checkout -b features/divide_playbook

Git 2.23以降は

$ git switch -c features/divide_playbook

ブランチ間の差分

ブランチ名を引数に実行すればOK

git diff <branch1-name> <branch2-name>

ローカルブランチの削除

$ git branch --delete features/swapoff features/replace-yum-config-manager 

↑複数指定した場合

ローカルブランチの強制削除

未マージのコミットがあったりすると削除できないけど、-Dで強制的に削除できる

$ git branch features/foobar -D

ローカルブランチ名の変更

# 現在のブランチ名を変更
$ git branch -m <new-branch-name>
# 指定ブランチを変更
$ git branch -m <current-branch-name> <new-branch-name>
# 強制変更 (GitHubのquick setupの表示だとこれ)
$ git branch -M main
# --helpを見る限り`--move --force`っぽい

作成済みリポジトリのmastermainに変更するのもこれ。

git branch -m master main

ブランチをpush

# 同じブランチ名でpush
$ git push origin <local-branch-name>
# 異なるブランチ名でpush
$ git push origin <local-branch-name>:<remote-branch-name>
# 複数ブランチまとめてpush
$ git push origin <branch-name-1> <branch-name-2>

リモートのブランチ一覧

$ git branch -r

リモートブランチをfetch

$ git fetch origin <remote-branch>

リモートのブランチをローカルの追跡ブランチに取り込む。
これでローカルブランチにmergerebase出来る。

リモートブランチを削除

$ git push origin :<remote-branch-name>

git remote -rで出力されるのにすでにリモートには無い場合はgit fetch --pruneで参照のないブランチは消える

$ git push origin :<remote-branch-name>
error: failed to push some refs to 'github.com:******'   # 消せない
$ git fetch --prune

stash

一覧

stashに退避している内容の一覧

git stash list

退避

現在の未コミットの変更をstashへ退避

git stash save

名前付きの退避

git stash save comment

list実行時にコメントが表示される。

退避データをもとに戻す

git stash pop

退避データの詳細

git stash show stash@{0} -p

これでdiffを確認できるできる。
-p無しの場合はサマリのみ。

tag操作

タグ操作は基本的にブランチと同じ。

tagを作成

最新コミットへtagを作成

git tag -a tag-name -m 'coment'

tagをpushする

デフォルトではtagはpushされない

$ git push --tags

tagをcloneする

指定tagをcloneするのはブランチと同じ

$ git clone -b <tag-name> <repository>

tag一覧

$ git tag

-lは付けても無くてもtag名一覧が表示される。

$ git tag -n

-nを付けるとタグのコメントも一緒に表示される。

指定tagにブランチ切り替え (tagをチェックアウト)

$ git checkout <tag-name>

switchの場合はオプションが必要?

$ git switch --detach <tag-name>

移動

ディレクトリを新規作成しそこへ既存ファイルを移動

$ mkdir dir
$ git add dir
$ git mv managed.file dir/

削除

ファイルを削除

$ git rm /path/to/file

実ファイルも消える

ディレクトリを削除

$ git rm -r /path/to/directory

実ファイルも消える

バージョン管理から外すのみ

$ git rm --cached /path/to/file

Git上は削除されるがファイルシステムには残る。
ディレクトリの場合は-rもつける。


git rm直後は、git statusで削除したものがdeletedと表示されステージング状態なので、commitすればリポジトリに反映される。

Untrackedファイルを削除する

-nでファイルを確認

$ git clean -n [path/to]

-fで削除する。

$ git clean -f [path/to]

コミットログ

ログを見る

$ git log

k8sのクセでlogsって入れると怒られる

1行のシンプルなログで出力

$ git log --oneline 

マージ/ブランチなどのツリーも表示

$ git log --oneline --graph

別ブランチのログ

$ git log --oneline --first-parent <branch-name>

コミット時の対象ファイルを表示

pullのように変更量などを表示

$ git log --stat
:
:
commit 8331291c45b99411ee14076cc0e73dddfeafa153 (HEAD -> main, origin/main, origin/HEAD)
Author: zaki-lknr <zaki.hmkc+github@gmail.com>
Date:   Wed Sep 15 16:44:39 2021 +0900

    add: ansible/directives: whenでリスト

 docs/Ansible/directives.md | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

statusのときのように変更種別の表示

$ git log --name-status
:
:
commit 8331291c45b99411ee14076cc0e73dddfeafa153 (HEAD -> main, origin/main, origin/HEAD)
Author: zaki-lknr <zaki.hmkc+github@gmail.com>
Date:   Wed Sep 15 16:44:39 2021 +0900

    add: ansible/directives: whenでリスト

M       docs/Ansible/directives.md

--onelineとの併用も可

差分

ブランチ間の差分

ブランチ名を引数に実行すればOK

git diff <branch1-name> <branch2-name>

whitespace無視

$ git diff -w
   -w, --ignore-all-space
       Ignore whitespace when comparing lines. This ignores differences
       even if one line has whitespace where the other line has none.

この行をコミットしたのは誰 (git blame)

これで行ごとの最終コミットのID、ユーザー名、コミット日時が出力される

git blame <filename>

git blameで特定コミットを除く

例えば過去に「ファイルの改行コードを変更」というコミットがあると、全ての行で変更が発生することになるため、git blameを使ってもそれ以前のコミットを確認できない。
こういう時は特定のコミットを除く--ignore-revオプションを使って除外したいコミットを指定する。

git blame --ignore-rev <除外したいコミットID> <filename>

除外対象が複数ある場合は、その分指定すればOK

サブモジュール

カレントのリポジトリに別のリポジトリをサブモジュールとして追加

ローカルリポジトリの作業ディレクトリ内にbsky-clientディレクトリへ別リポジトリのソースを取得する。

git submodule add https://github.com/zaki-lknr/bsky-client.git bsky-client

サブモジュールを更新する

対象ディレクトリでgit pullを実行する。
親リポジトリでgit diffすれば更新されていることを確認できる。

$ git diff
diff --git a/bsky-client b/bsky-client
index ae590a7..2a0550c 160000
--- a/bsky-client
+++ b/bsky-client
@@ -1 +1 @@
-Subproject commit ae590a7142b82f0cb77d4fd7b970c6ab3a9dc8fa
+Subproject commit 2a0550cfc11ca1d06f13596f2eb087cc75dcdf9b

前の状態に戻す

指定コミットの状態に戻す

git reset --hard '対象のコミットID'

reset --hardコミットの取り消しにも使用する

その他

概略(語弊あるかも)

  • HEAD は最新(カレント)
  • HEAD~ 1個前
  • HEAD~1 同上(1は省略可能)
  • HEAD~2 2個前

git logした時の、

ec33978 (HEAD -> main) add: docker: ボリュームのリンク追加
bd9aa93 add: ansible/config: ansible.cfgサンプル
bc5eb56 add: git/configure: git-prompt設定後のPS1環境変数
:

に対して、

  • ec33978HEAD
  • bd9aa93HEAD~
  • bc5eb56HEAD~2

^~は基本は同じ。
HEADの一つ前ならHEAD^またはHEAD~、2つ前ならHEAD^^またはHEAD~2になる。
ただし厳密には違うもので、^はブランチのマージで親が複数ある場合に使用する。

コミットを指定するときに、(チルダ)と^(キャレット)を使ってあるコミットからの相対位置で指定することもできます。この時に、よく使われるのがHEADです。(チルダ)を後ろに付け加えることで何世代前の親かを指定することができます。^(キャレット)は、ブランチのマージで親が複数ある場合に、何番目の親かを指定することができます。

ブランチの切り替え|サル先生のGit入門【プロジェクト管理ツールBacklog】

.gitignore

空のディレクトリを維持するための、 .gitkeep と .gitignore の使い分け - Qiita