1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

実戦用Gitまとめ

Last updated at Posted at 2023-05-03

何はともあれ

ブランチ戦略

  • git flowやgithub flowを応用しながらブランチをたくさん切る。
  • 大手アパレルなどでgitブランチ戦略を担当したりして来たが
    fetureブランチに個人名を入れたブランチを切るのを強くオススメしている。
    (feature/aaa/aaa_bob、feature/aaa/aaa_john、といった具合)
    気軽にpushできるし、featureブランチはrebaseすることが多いためオリジナルを残して事故に備えやすい。
    ただし後で消します。恥ずかしいし。

コミットIDの別名

  • origin : git clone http://HOST/PROJECTとしたときのURLの別名。
  • origin/BRANCH1 : リモートのBRANCH1の先頭コミットIDを指す別名、とは言え最新化しないと古くなる。追跡ブランチ。git branch -aで一覧したときは「remotes/origin/BRANCH1」と表記される。
  • HEAD : 現在チェックアウトしているブランチの先頭コミットを指す、コミットIDの別名。git log の先頭であり git reset で移動させられる。
  • コミットID ab1Cef2H に対しての前回コミットの別名は ab1Cef2H^で、この ^ はよく使うdiff HEAD^ HEAD も頻繁に使う。

ユーザ設定の方法

  • git config user.name USERNAME (普段はgit configで設定する)
  • git config user.email MAILADDRESS
  • git commit --amend --author="USERNAME <MAILADDRESS>"

設定ファイルの在り処

  • リポジトリ単位 : .git/config (git config -eで開く)
  • ユーザ単位 : ~/.gitconfig (git config --global -eで開く)
  • システム全体 : (app-path)/etc/gitconfig (git config --system -eで開く)

各スペースの状態の確認 (手癖で使う)

  • git status : ワークツリー(赤色)とインデックス(緑色)が見れる。コミットされたもの(ローカルリポジトリ)は見れない。
  • git log : コミットされているものを見る。最も打つコマンドが statuslog
    何かするたびに打ってその時その時のコミットIDをコンソールに残しておく。それらのコミットIDが様々な事故から救ってくれる。git log -3などで上手くコンソールに残して行こう。
  • git diff : ワークツリーとインデックスとの比較。何をaddしようとしているかを知るときに使う。
  • git diff --cached : インデックスとHEADの比較。何をコミットしようとしているか知るときに使う。

ログの確認

  • git log --decorate --graph --branches --tags --remotes (おすすめ)
  • git log --oneline --decorate --graph --branches --tags --remotes
  • git log --graph --date=short --decorate=short --pretty=format:'%Cgreen%h %Creset%cd %Cblue%cn %Cred%d %Creset%s'
  • git log -3
  • git log -5
  • 以前はエイリアス必須だったが、現在のGitBashは--decorateがなくても色が付くため、エイリアスなしでも運用できる。

インデックスへの追加と削除

  • git add . : カレントディレクトリ配下 (普段はgitディレクトリの頂上にいるのでこれを使う)
  • git add -A : gitディレクトリ全て (ほとんど使わない)
  • git reset FILEPATH1
  • git reset FILEPATH1*.txt
  • git reset /DIRNAME/ (「/DIRNAME/*」では無反応)

リモートブランチからの取り込み方

  • git clone http://HOST/PROJECT -b BRANCH1
  • git fetch origin : ローカルの追跡ブランチであるorigin/BRANCH1, origin/BRANCH2...を全て最新化する。 (便利だがダウンロード容量に注意)
  • git fetch origin BRANCH2 : origin/BRANCH2を最新化し、FETCH_HEADに入れる
  • git fetch origin BRANCH3:BRANCH3 : ローカルにorigin/BRANCH3とBRANCH3の2つを作る。新しくブランチを落とすときはこれ。「git fetch origin BRANCH3 && git branch BRANCH3 origin/BRANCH3」と同等。
  • git pull origin BRANCH1
    有名なコマンドだが使う必要がないpull を最新化だと思っている人も多いが、最新化は fetch
    ブランチ名を指定せず実行するとローカルの全ブランチに対して行うため危険
    FETCH_HEADの状態を確認せずにいきなり merge (設定によっては rebase) するため予期しない変更を取り入れたりconflictを起こす恐れがある。そのため fetch してから、log FETCH_HEAD で状況を確認しつつ、 merge FETCH_HEADrebase FETCH_HEADreset --hard FETCH_HEAD などの選択をすればいい。
  • 手元の状態を残しながらローカルブランチを最新化したい場合(origin/BRANCH1 としてではなく BRANCH1 として手に入れたい場合)、一度バックアップブランチを作って手元の状態をコミットとして退避させるといい。
    1. git fetch origin BRANCH1
    2. git checkout -b BK
    3. git add .
    4. git commit -m "MESSAGE"
    5. git checkout BRANCH1
    6. git reset --hard FETCH_HEAD

コミットはしたくないが手元の状態を一旦残したいと感じたとき

まずはコミットして一呼吸置く。コミットは reset でアンステージしてすぐ戻せる。
コミットしてコミットIDを控えておけば、その後アレコレした後でも一旦残したいと感じたときの状態に戻せる。

リモートへの反映

  • git push origin BRANCH1 または git push origin BRANCH1:BRANCH1
    (ブランチ名を指定せず実行するとローカルの全ブランチがリモートに飛ぶため非常に危険)
  • リモートブランチを消すときは git push origin :BRANCH1。思っている以上にお手軽。

別のブランチからマージを避けて特定のファイルだけ持ってきたい

  • git checkout BRANCH1 -- FILEPATH1 FILEPATH2
    ややこしいが checkout はブランチ切り替え以外に、別ブランチからファイルを持ってくる機能がある。

コミットを別のブランチに付け替えたいがマージはしたくはないとき

  • 一度 merge してから reset してコミットし直す。以下はBRANCH1からBRANCH2への付け替え。
    1. git checkout BRANCH2
    2. git merge BRANCH1
    3. git reset HEAD^
    4. git commit -m "MESSAGE"
  • HEADではなくHEAD^^辺りのコミットを別のブランチに付け替えたい場合は cherry-pick。使いすぎ注意。

ローカルの変更の戻し方

  • git reset --hard HEAD && git clean -df : 何もかもごっそり戻したいとき
    clean -df は空ディレクトリを消すため、残したいときは .gitkeep を置く。
  • HEADを色々と移動させていてリモートブランチのHEADに戻したい場合は
    git reset --hard origin/BRANCH1
  • ファイル単位でリモート追跡ブランチから戻したいときは
    git checkout origin/BRANCH1 -- FILEPATH1 FILEPATH2 FILEPATH3
  • git branch -f BRANCH1 COMMITID : BRANCH1COMMITIDで上書き。今いるブランチ以外で使えて非常に強力。

コミットコメントやauthorやemailを直したい場合

  • コミットコメントを直す場合は
    git commit --amend -m "MESSAGE"
  • authorやemailも直すなら
    git commit --amend -m "MESSAGE" --author="user.name <user.email>"
  • 直近の4つに対して行う場合
    1. git rebase -i HEAD~4 でvimを開いて、先頭を全てe(edit)にして:wqするとrebaseモードになる。
    2. git commit --amend -m "MESSAGE" --author="user.name <user.email>" && git rebase --continueを4回やるとrebaseモード終了。

リモートの戻し方

  • git reset COMMITID && git push -f origin BRANCH1
    個人用のリモートブランチならバンバン使っていい。origin/BRANCH1をfetchしていなければ--force-with-leaseで他の作業者のコミットを消してしまう危険性を下げられるらしい。全く関係のないブランチで上書きしてしまったりなどのミスが怖い。
    万が一に備えて必ず元のリモートヘッドのコミットIDをどこかにバックアップしておく。コミットIDは、push前にgit logで出力してもいいし、force-push時の + 1234abc...5678def main -> main (forced update)というログでもいい。(左側がオリジナルのコミットIDになる)
    JenkinsがGitHUB上でforce-pushをして元に戻せなくなったことがある。GitHUB上ではreflogができない(元のコミットIDを見失うと元に戻せなくなる)。著名なプロジェクトだったためか、最終的にはGitHUB側が対応をして難を逃れた。
    参考 : 本の虫: Jenkinsの開発者、間違えて一ヶ月前のローカルレポジトリをgit push --forceしてしまう
    それを受けて(?)、GitHUBではブランチごとへのforce-pushを禁止できるようになった。(masterのみ禁止、など)

マージと競合の解消

  • git merge BRANCH2 --no-ff
    --no-ffを付ける。--no-ffを付けないとコミットログにマージの痕跡が残らない。痕跡を残したくないと思っても結局conflictが起こったものはマージ跡が残り、残ったり残らなかったりカオスな状態になる。
    --no-ffを付けるというルールを採用するプロジェクトもある。そのルールで良い。
  • git merge --abort でマージをやめる (mergeモード中はブランチ名が(master|MERGING)になる、それを抜ける)
  • git checkout --ours -- FILEPATH1 (git checkout HEAD -- FILEPATH1 でいい)
  • git checkout --theirs -- FILEPATH1 (git checkout BRANCH1 -- FILEPATH1 でいい)
    一旦theirsで checkout して、他人のコミットをベースにして自分の修正を入れ直すことが頻繁にある。diffは基本的には git diff HEAD で行う。
  • git merge --continueでマージの内容を決定する (エディタ等でconflictを解消した後にやる)

部分操作

  • git add -p FILE + eモード : エディタでファイルの変更の一部だけを選んでインデックスに追加する。複数の機能変更を同じファイルにしてしまった場合に利用する。意味のあるコミット単位にするための意識高い系コマンド。

  • git cherry-pick : 他ブランチをmergeしたくはないが、そのブランチの一部コミットはmergeしたい場合に利用する。mergeの痕跡が残らず、ツリーがカオスになるためおすすめできない。必要になった時点で何かがおかしい。以下が参考になる。

    cherry-pick 運用の地獄から這い上がった話をしよう
    筆者もプロジェクトの最初からいたわけではない上に、初期メンバーも今は一人もいないので詳細はわからないが、develop ブランチを、いわゆる feature ブランチのように使ってしまったことが発端らしい。

タグをつける

  1. git tag -a TAGNAME -m "MESSAGE"
  2. git log -1 --decorate
  3. git push origin BRANCH1 TAGNAME

タグを消す

  1. git tag -d TAGNAME
  2. git push origin :TAGNAME

リポジトリのプロジェクトをcloneして、それを別のリポジトリにpushする

  • git clone git@github.com:XXX.git - b BRANCH1
  • git remote remove origin
  • git remote add origin git@github.com:YYY.git
  • git push origin BRANCH1

FETCH_HEADからブランチを作成する

  • 意外とよくやる操作。
    git branch BRANCH1 FETCH_HEAD または git branch BRANCH1 origin/BRANCH1

別リポジトリからブランチを取り込む

  • git fetch 別リポジトリURL BRANCH1:BRANCH1

複数行のコミットコメントでコミットする

  • -mを付けずにgit commit。viが開き、wqすればコミットされ、q!すればコミットされない。git logで他のメッセージを参照しつつコミットコメントを書けない上に、oneline指定のgit logに出てこなかったりするため使い勝手が非常に悪い。gitはちょくちょくコミットするものなので、複数行書く必要がある時点でコミット単位が粗いとも言える。長文コメントが必要なコミットになった場合は、別ブランチを切って --no-ff でマージしてそれを知らせたりタグを切ったりして、大きな分岐点になったことを残しておくと良いかも知れない。

rebaseの注意点

  • 有名なコマンドだが、Git Bash上に残したコミットIDやreflogでしか戻せずforce-pushと併用されることが多い、ちょっと危ないコマンド。ただしブランチを上手く運用するためには rebase が必要。rebase を活用できる人はgitを上手く使えていると思って大丈夫。

  • 戻すとき

    • git logなどで残しておいたコミットIDでreset --hard。一応reflogで上から3, 4番目辺りに出てくる「reset: checkout BRANCH1」と書かれているコミットIDにreset --hardしても戻せるが、rebaseの後に色々操作したりすると行方不明になる。
  • 使うとき

    1. ローカルで作成した自分の作業ツリーを作り直したりコミットコメントを修正したりするとき。(rebase -i)

    2. ローカルで作成した自分の作業ツリーが分岐した場合にそれを一本化してリモートにpushしたいとき。

    3. リモートからfetchしてきたものを一番下にして自分のツリーをそこから始めたいとき。

    4. リモートツリーを一本化する場合。force-pushと歴史改変が行われる。以下が参考になる。

      3.6 Git のブランチ機能 - リベース
      マージとリベースではどちらがいいのか。
      お察しのとおり、単純にどちらがよいとは言い切れません。
      Git は強力なツールで、歴史に対していろんな操作をすることができます。しかし、チームやプロジェクトによって、事情はそれぞれ異なります。
      あなたは既に、両者の特徴を理解しています。あなたが今いる状況ではどちらがより適切なのか、それを判断するのはあなたです。

      一般論として、両者のいいとこどりをしたければ、まだプッシュしていないローカルの変更だけをリベースするようにして、 歴史をきれいに保っておきましょう。プッシュ済みの変更は決してリベースしないようにすれば、問題はおきません。

ローカルでプロジェクトを作ったので、それを元にGitHUBのリポジトリを作りたい

  • 普通この順番。まずはGitHUBにリポジトリを切ってcloneしてから、ローカルで新規プロジェクトを作成するという順番もあるにはあるが。
  1. まずはGitHUBに中身が空のリポジトリを作成する。(そのとき.gitignoreやLICENSEを用意してもOK)
  2. ローカルに作ったプロジェクトのトップディレクトリでgit initしてgitプロジェクトにする。
  3. そこでgit remote add origin git@github.com:xxx/yyy.gitしてGitHUBで作成したリポジトリのURLを登録する。
  4. git fetch origin main:mainでGitHUBリポジトリを落として来る。 (今のGitHUBのデフォルトのブランチはmainになっている) (Git Bashもmainになっている場合は別名でアレコレすれば良し)
    • 「Please make sure you have the correct access rights」が出た場合 : ローカルでssh-keygen -t rsaしてとりあえず全部Enterを押した後、「~/.ssh/id_rsa.pub」の内容をコピーしてGitHUBのSettings -> SSH keysに登録
    • 「push declined due to email privacy restrictions」が出た場合 : GitHUBのSettings->Emailからprivate設定を公開に変更 (迷惑メールがわんさか来るため危険)
  5. git checkout mainfetchしたブランチに移動する。 (GitHUBで作成した初期ブランチはmainブランチを想定する)
  6. 念のためgit logでGitHUBで行ったinitial commitが存在するか確認する。
  7. 念のためgit statusでローカルで作成したプロジェクトが赤くなっている(ワークツリーにいる)ことを確認する。
  8. コミット前にgit config user.name USERNAMEgit config user.email MAILADDRESSでAuthorを設定しておく。
  9. git add .してgit commit -m "MESSAGE"してコミットログを作成する。
  10. 最後にgit push origin main:mainでGitHUBにpushする。 (GitHUBで作成した初期ブランチはmainブランチを想定する) (-uオプションがあるとoriginを付けなくても良くなるため初回のpushで推奨されているが、個人的には必要性を感じない)
  11. GitHUB上で無事にpushされていることを確認して、めでたしめでたし。

実戦で使用しているGitBash用エイリアス (オリジナル)

vim ~/.bash_profile
alias f='git fetch origin'
alias a='git add'
alias b='git branch'
alias com='git commit'
alias coma='git commit --amend'
alias ch='git checkout'
alias st='git status'
alias d='git diff'
alias dc='git diff --cached'
alias l='git log --decorate --graph'
alias push='git push'
source ~/.bash_profile
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?