今回はGitでよく使う基本的な操作を説明いたします。
すべてコマンドラインでの説明となります。
Gitを使用している方は、SourcetreeなどのGUIツールを使っている場合もあると思います。
コマンドラインでの操作が分かれば、感覚でGUIでの操作も分かって、つぶしが効くと思います。
そのためコマンドラインに拒絶反応を示さずに聞いていってほしいです。
第4弾で実際に僕が使っている応用編をやるので、そちらでやればコマンドラインでも使っていけると思える。。はずです。
余談ですが、僕はGitが流行りだした頃から使っています(自慢ではなく辛かったです。)
その頃はSVNからの移行が必要だったり、使っていたEcripseなどの統合開発環境で操作が難しく使えず、
必要に迫られてコマンドラインで使っていたら、今でもコマンドラインを使っている形です。
サーバーサイドエンジニアのdaijinloadです。
Node.js, TypeScript, Java, Golang, PHPあたりを業務でやったことがあります。
サブ的にではありますが、ReactやFlutterなどのフロントエンドも経験があります。
Ubuntu 20.4ベースの、LinuxMint 20.3(HWE)をVirtualBoxに入れて起動しています。
- 第二弾でGitをセットアップした後の環境です。
Gitのリポジトリをcloneすると下記のように展開されます。
- working-directory(実際のファイル)
- staging-area(またはindexと呼ぶ)(addしたファイルが入る場所)
- local-repository【表記:main】(commitしたファイルが入る場所)
- remote-repository【表記:origin/main】(変更不可・サーバと同期するだけ)
- remote-repository【表記:origin main】(本体)
Gitの各種コマンドが、Gitの構造のどこを更新しようとしているのか?が分かるようになると混乱することは無くなると思います。
リポジトリを最初に作成すると、mainブランチが作成されます(昔はmasterブランチが作成されました。ポリコレで変更となりました。)
プルリクエストを使えるなどあるので、作業するときはブランチを切ってから作業しましょう。
ブランチの名前は何でも良いのですが、修正目的によって命名ルールがあったほうが分かりやすいとのことで、僕は下記としています。
- featureブランチ【feature/hoge】(新機能開発用)
- refactorブランチ【refactor/hoge】(リファクタリング用(機能変更は無し))
- fixブランチ【fix/hoge】(バグFix用)
- docブランチ【doc/hoge】(ドキュメント用)
- testブランチ【test/hoge】(テストのみの修正や追加用)
実際にブランチを切るコマンドは下記です。
git checkout -b feature/hoge
Gitはコミットを行うと、コミット前のハッシュ値や追加したファイル情報などから新たなハッシュ値を生成します。
基本的にハッシュ値の集合体に名前を付けたものがブランチなので、ブランチ名はさほど重要では無いのです。
ハッシュ値だけでやろうとすると大変ですし、見づらくもなるのでブランチ名を付けているイメージでいてほしいです。
実際に見てみると下記ですね。
$ git log
commit 2d5139d600fd77d6e6a5931554981a707464cb3a (HEAD -> main, origin/main, origin/HEAD)
Author: daijinload <[email protected]>
Date: Thu May 5 21:45:02 2022 +0900
add 1
commit a4ab5558407732f4d94c44c717504181f1b3e96c
Author: daijinload <[email protected]>
Date: Thu May 5 21:40:25 2022 +0900
Initial commit
git status
git log
git log --pretty=fuller
ファイルを変更(working-directoryが変わる)
git add ファイル名(指定したファイルの変更をstagingエリアに移動)
git add file1 file2... (複数指定もできる)
git add --all(全部の変更をstagingエリアに移動)
git commit -m 'メッセージ'(stagingエリアの変更をlocal-repositoryにコミットする)
git push origin ブランチ名(local-repositoryの内容を、サーバのrepositoryに反映する)
git push -f origin ブランチ名(通称フォースプッシュ)(過去改変を行ったりすると変化がありすぎてpushできなくなるので強制反映する)
git commit -am '追加'(stagingを飛ばして、local-repositoryにコミットする)
※新規にファイルを追加した場合は、変更扱いとならずにコミットできないため、addコマンドが必要になります。
おすすめは、fetch + rebaseです。
git fetch(ローカルのremote-repositoryとサーバのファイルを同期する。)
git rebase origin/feature/hoge
pullは、fetch + mergeという作業になるので、mergeされたくない場合は、rebaseオプションを付けるかコンフィグに足しておく。
git pull --rebase
# configに足す場合
git config --global pull.rebase true(コンフィグに設定しておく)
git pull
自分の修正が無くなるので注意です。
消えてほしくない場合は、ブランチを切って退避させると良いです。
git reset --hard ハッシュ値
git reset --hard ブランチ名
余談だが、下記のようにやれば、サーバのファイルで置き換えることも出来る(自分の修正が無くなるので注意!!)
git fetch
git reset --hard origin/feature/hoge
git rebase -i ハッシュ値
or
git reset --soft ハッシュ値
git push -f origin feature/hoge(force pushとなるのでバックアップ必要)
git cherry-pick ハッシュ値
たいていハッシュ値が被らないので、ブランチ指定しなくても持ってこれます。
持ってきたコミットは、新しいハッシュ値が振られるので、自分で変更してコミットしたときと同じ扱いとなります。
直前にバックアップしている前提となります。
cd バックアップフォルダ
git clone [email protected]:daijinload/test2.git
cd test2
git checkout feature/hoge
git fetch
git reset --hard origin/feature/hoge
# ---
# 上記までが事前準備
git push -f origin feature/hoge
特定のユーザを狙ってユーザを変更するやり方。
$ FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --commit-filter '
if [ "$GIT_COMMITTER_EMAIL" = "[email protected]" ];
then
GIT_AUTHOR_NAME="daijinload";
GIT_AUTHOR_EMAIL="[email protected]";
GIT_COMMITTER_NAME="daijinload";
GIT_COMMITTER_EMAIL="[email protected]";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
# 確認
$ git log --pretty=fuller
ブランチを切っていた場合、下記で無かったことにしてコミットすれば終わりです。
git reset --soft ハッシュ値
git add --all
git commit -m 'message'
同じブランチで作業していて、コンフリクトが起きた場合の対処法です。
- 複数コミットがある状態でのマージは大変なので、事前に1コミットの状態に過去改変しておく。
- 背景 or 原因(機能追加は背景。バグfixの場合は、原因を書く)
- 修正内容
- 連絡事項(マージするときは消しておく)
イメージとしては、AWSのワンページャーが近いものだと思います。
お互いのメンタルのために、指摘の仕方は、人格攻撃とならないように最新の注意を払うことが必要です。
おすすめは、すごく偉い人のソースコードに指摘をするイメージが良いかと思います。
- Create a merge commit(細かいコミットを残したいかつ、マージコミットしたい場合。)
- Rebase and merge(細かいコミットを残したいかつ、マージコミットを作成したくない場合。)
- Squash and merge(シングルコミットになります。シンプルです。)
個人的には、「Squash and merge」がおすすめです。
コミットを細かくキレイにしてマージするという作業は、個人的には無駄だと思います。
忙しいときにコミットを綺麗に調整している人を見ると、いいから早くしてくれと思います。。。
バグの調査などでも、基本はリリースしたソースコードで調査できれば良いため、
コミットが綺麗で良かったという経験は無いです。
# ブランチ名で指定
git checkout origin/main file1.txt
# ハッシュ値でも指定できる
git checkout c3cc481c13de40e69bd042ced86f54f7dea33567 file1.txt
ファイルを修正中に戻したくなった場合も、1ファイルだけ戻せます。
git reset --hard
などだと、全体的に戻ってしまうので、こちらがおすすめです。
文字列の一括置換などで、修正ファイルを確認している時に、関係ないファイルを戻したりするときとか便利です。
タグは、リリースした時に作成しておくものです。
もし何かあった問題があった場合も、タグをリリースする運用であれば調査がしやすいです。
作成しなくても運用できますが、releaseブランチも作らずにmainブランチだけでやっていると、mainブランチのどの時点が問題なのか?パッとわからなかったりします。
ブランチだと、pushが出来てしまうため変化してしまいリリースバージョンの管理としては不十分かもしれません。
しかし、タグだとpushすることが不可能なため、リリース物のバージョン管理という意味では作ったほうが良いと思います。
ただ、Microsoftなどはリリースブランチで運用をしたほうが、タグの運用よりも良いなどと言っていたりもします。
Git 分岐ガイダンス - Azure Repos | Microsoft Docs
下記は引用です。
- タグからブランチに変換しないと、bugfixなどの変更を反映できない。
- タグからの変換コマンドなどを覚える必要がある。
- タグを打ち忘れる場合がある。
このあたりは、僕の見解を次回のブランチ戦略などで話す予定です。
# 一覧表示
git tag
# タグ付け(local repositoryに反映)
# (タグ名はv2.0.1などのセマンティックバージョニングでも良い)
git tag -a v2022.05.19 -m 'hoge機能リリース' ハッシュ値
# タグ消す(失敗したときとか)
git tag --delete v2022.05.19
# リモートサーバにpushする(remoteサーバに反映)
git push origin v2022.05.19
# タグをブランチに変換する(この記事のブランチを切る方法と同じ)
git checkout タグ名
git checkout -b ブランチ名