LoginSignup
1
0

実戦用Gitまとめ

Last updated at Posted at 2023-05-03

何はともあれ : Git超絶まとめ

名称

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

ユーザ設定

  • 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 diff : ワークツリーとインデックスとの比較。何をaddしようとしているかを知るときに便利。
  • git diff --cached : インデックスとHEADの比較。何をコミットしようとしているか知るときに便利。
  • git diff origin/BRANCH1 HEAD : リモートブランチをfetchしてから行うと、何をpushしようとしているかが分かる。

ログの確認

  • 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
  • 以前はエイリアス必須だったが、現在のGitBashは--decorateがなくても色が付くため、エイリアスなしでも運用できる。

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

  • git clone http://HOST/PROJECT -b BRANCH1
  • git pull origin BRANCH1
    有名なコマンドだが使う必要がない。ブランチ名を指定せず実行するとローカルの全ブランチに対して行うため危険で簡単には元に戻せない。また diff せずに merge するため予期しない変更を取り入れることになる。pull より fetch の方が安全で便利。fetch して diff した上で mergerebase など次の行動を判断すれば良い。
  • 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」と同等。

最新の状態を取り込む

  • stashしてstash popすると競合したときstashを見失いがち。別ブランチに退避させると安心。
    1. git checkout -b BRANCH1_BK
    2. git add .
    3. git commit -m "MESSAGE"
    4. git checkout BRANCH1
    5. git fetch origin BRANCH1
    6. git rebase origin/BRANCH1

リモートへの反映

  • git push origin BRANCH1
    (ブランチ名を指定せず実行するとローカルの全ブランチがリモートに飛ぶため非常に危険)
  • 自分のコミットがfowardされてツリーに繋がる場合もある(pushしたローカルブランチが最新の状態ではない可能性もある)ため、push後にfetchしておくといい。

編集途中でのブランチの切り替え方

  • stashしてstash popすると競合したときstashを見失いがち。別ブランチに退避させると安心。
    1. git add . && git commit で一旦コミットしてしまう。 (stashの代わり)
    2. git checkout BRANCH2
    3. git checkout BRANCH1 -- FILEPATH1 FILEPATH2 で編集していたファイル達を持ってくる。
    4. git checkout BRANCH1 && git reset HEAD^」で元に戻しておく。 (または git branch -f BRANCH1 COMMITID)

コミットを別のブランチに付け替える

  • マージするとツリーが繋がっちゃうけどそれは避けたいとき。
    1. git reset HEAD^で1つ前のコミットに移動し、HEADをコミットしようとしている状況にする。
    2. git checkout BRANCH2
    3. git commit -m "MESSAGE"

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

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

ローカルの変更の戻し方

  • git reset --hard HEAD
    ゴミが残ったらgit clean -dfする。ただしその際にコミットできない空ディレクトリを消してしまうため、必要に応じて.gitkeepを置く。
  • HEADを色々と移動させていてリモートブランチのHEADに戻したい場合はgit reset --hard origin/BRANCH1
  • git checkout origin/BRANCH1 -- FILEPATH1 FILEPATH2 FILEPATH3 : 指定ブランチを元にファイル単位で戻す。
  • git branch -f BRANCH1 COMMITID : BRANCH1COMMITIDで上書き。今いるブランチ以外で使えて非常に強力。
  • 直近の4つのコミットのコミットコメントやauthorやemailを直したい場合
    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 --theirs FILEPATH1
    一旦theirsをcheckoutして、他人の変更を基本にして、自分の修正リビジョンとdiffを取りながら修正するのが吉。diffは具体的にはgit diff HEADコマンドで行う。git diffだと作ろうとしているマージコミットとのdiffになる(?))
  • git merge --continueでマージの内容を決定する (エディタ等でconflictを解消した後にやる)

部分操作

  • git add -p FILE + eモード : エディタでファイルの変更の一部だけを選んでインデックスに追加する。複数の機能変更を同じファイルにしてしまった場合に利用する。意味のあるコミット単位にするための意識高い系コマンド。
  • git cherry-pick : 他ブランチをmergeしたくはないが、そのブランチの一部コミットはmergeしたい場合に利用する。mergeの痕跡が残らず、ツリーがカオスになるためおすすめできない。必要になった時点で何かがおかしい。

タグをつける

  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からbranchを作成

  • 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の注意点

  • 有名なコマンドだが、基本的にはreflogでしか戻せずforce-pushと併用されることが多いちょっと危ないコマンド。

  • 戻すとき

    • 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に空のリポジトリを作成する。今はGitHUBがgitignoreを生成してくれるので便利 (以前はgitignore.ioなどを利用していた)
  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になっている)
    • 「Please make sure you have the correct access rights」が出た場合 : ローカルでssh-keygen -t rsa MAILADDRESSした後、「~/.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 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
0
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
0