Gitコマンドとオペレーション - foolmacky/DevelopDocs GitHub Wiki

■ 基本的な流れ

  • 更新したいremote共通リポジトリを自分のremote privateリポジトリにforkする(GitHub UI上で)
  • remote privateリポジトリをoriginとしてローカルに取得、ブランチを作成して編集、更新、テスト
  • git cloneした時点で、自動的にorigin設定される
  • remote共通リポジトリは upsteamとしてnetwork設定する。直接更新しないので、httpsでのURLで。
  • originに対してlocalのブランチをpush
  • upstreamに対してoriginのブランチからPull Requestを作成(GitHub UI上で)
  • 現在ではmasterブランチはmainに移行しつつある
git clone [email protected]:hoge/hoge.git
cd hoge
git remote add upsteam git://github.com/hoge/hoge.git

//cloneはhttpsでも
git clone https://github.com/hoge/hoge

//ごちゃごちゃしてわけわかになったら、再度矯正取得・更新
git checkout master && git fetch upstream && git reset --hard upstream/master && git push origin master
or
git checkout main && git fetch upstream && git reset --hard upstream/main && git push origin main

//カレントブランチ(master以外でもOK)からブランチを作成する
git checkout -b [branch name]

git status
git add -u
git push origin hoge
//pushで指定しているbranchはリモート側
//remote共通リポジトリでPull Requestを作成

//設定値の参照
git config --list

//remote設定の確認
git remote -v

//remote設定の変更。git remote -vの値を見ながら行う
git remote set-url origin [new URL]

//更新履歴
git log --graph

//コミットの更新内容を見る
git show [commit ID]

//コミットの差分内容を見る
git diff [commit ID] [commit ID]

//git add後のファイルの更新内容を見る
git diff --staged [ファイル名]

//remoteの他人のブランチを指定してローカルに取得する場合
git clone -b [branch name] [email protected]:[他の誰か]/hoge.git -b [branch name]

//特定のコミットをローカルに取得する場合、一旦masterをcloneし、コミットIDでcheckoutする
git clone https://github.com/hoge/hoge.git
cd hoge
git checkout [commit ID]
//この場合ローカルのブランチ名が [Head detatched ad <commit id>]といった名前になる
//git switchコマンドで変更できる
git switch [new branch name]

//すでにclone済みだったら、特定のbranchは git pullで取得する。localのブランチは存在していなくてOK
git pull upstream [remote branch:local branch]

//checkoutでも取得できる
git checkout -b [local_branch_name] origin/[remote branch name]

//pullはfetchとmergeを同時に実行する。実行するとマージした内容が表示される
git pull upstream hoge

//remote branchを削除する。コロンの左辺は通常はローカルのブランチを指定するが、それをブランクにする
git push origin :tmp
//または--delete optionをつける
git push --delete origin hoge
  • 基本的にgitコマンドはローカル側は現在のカレントが自動的に選択されることが多い

■ 毎回混乱するpush/pull

//push
//ローカルブランチ名だけ指定。リモートのブランチは自動的にローカルブランチと同じになる
git push [リモートリポジトリ] [ローカルブランチ]
git push origin local_hoge (リモートブランチは自動的に同じ名前が選択され、存在しない場合は作成される)
//異なる名前のリモートのブランチにpushする場合
git push origin [local branch]:[remote branch]
//local側をブランクにすると、リモートのブランチが削除される。

//pull
git pull [リモートリポジトリ] [リモートブランチ]:[ローカルブランチ]
git pull [リモートリポジトリ] [リモートブランチ](ローカルブランチは自動的に同じ名前が選択され、存在しない場合は作成される)
git pull origin remote_hoge:local_hoge
  • 特定のブランチでソースを更新すると、コミットするまではそのファイルはlocalのすべてのブランチで更新後の内容で見える。コミットすると初めてそのブランチのファイルとしてfixされ、他のブランチでは更新前のファイルが見えるようになる
  • ファイルの削除も同様で、削除をコミットするまではどのブランチでも削除されているように見え、コミットすると他のブランチでは存在していることになる
  • branchから更にbranchを生成することも可能。git branchする際のカレントが、元ブランチになる
  • originに、pushする際は、基本的にローカルのブランチ名と、リモートのブランチ名は合致させる。ローカルのカレントを別のブランチとしてpushする事はできない。
  • 特定のファイルのみ取得することも可能
//ファイルを見る
git show origin/master:./hoge.go
//ファイルを取得する
git checkout origin/master -- ./hoge.go

■ 日常のオペレーションあるある

  • branchを移動しようとしたときに、コミット前の更新ファイルが有ると移動できない。その場合、一旦その更新を棚上げする stash
  • stashは複数回可能で、指定して反映を戻すことができる
git stash

//棚上げの参照。p optionで差分を表示できる
git stash list -p

//棚上げを再度適用
git stash apply stash@{0}

//棚上げが要らなくなったら、削除
git stash drop stash@{0}
  • 他のブランチから、ファイルを持ってきてカレントブランチに上書きする
//ファイルの内容を確認
git show [ブランチ名:ファイル名(リポジトリルートからの相対パス)]

//ファイルの取得&上書き& add
git checkout [ブランチ名] -- [ファイル名(カレントディレクトリからの相対パス]
  • 修正したファイルをコミットの状態に戻す
git checkout -- [ファイル名]
//すべてのファイルをもとに戻すには
git checkout -- .
  • 一度addしてしまったファイルを戻す。すべて戻すならファイル名を指定しない
git reset HEAD [ファイル名]

//または
git rm --cached -r [ファイル名]
//こちらはファイルにdelete更新が立つ
  • 直前のコミットを取り消す
git reset --hard HEAD^
//hardは更新自体をなかったコトにする
//softはcommitを戻して、更新自体は残す=commitを戻すcommitを追加する
//すでにremoteにpushしている場合、戻してしまうとpushできなくなる
  • コミットを戻す
git revert [コミットID]
//コミットIDにrevert IDを指定することにより、「取り消しの取り消し」を行うこともできる
  • tagのみをremoteに付ける場合、originに対してのみ行う。ローカルに設定したものをremoteにpushする
//localにあるtagの参照
git tag

//localにつけて、push
git tag -a v1.0.1 -m "message."
git show v1.0.1
git push origin v1.0.1
  • remote側のログを見る
git log --online upstream/master
  • localの別のブランチから特定のコミット内容を取り込む
//cherry-pickコマンドを使う
//git logで取り込みたいコミットのコミットIDを確認
//取り込み先のブランチにcheckout
git cherry-pick <コミットID>
git log
//取り込まれていることを確認

■ PRのコンフリクトに対する対応

  • githubのUI上で行ってもいいのだが、localでconflict対応して、pushするほうがベターだと思う
  • masterブランチを最新にアップデートして、それを競合している作業ブランチにmergeする
//いつものやつ
git checkout master && git fetch upstream && git reset --hard upstream/master && git push origin master

//作業ブランチに移ってmerge
git checkout <作業ブランチ>
git merge master
//mergeするとconflict内容が表示されるはず。fileのconflictを修正する

//更新ファイルの確認
git status
git add <updated files> or git add -u

//更新をコミット、リモートにpushする
git commit
git push origin <ブランチ名>
//conflictは解消されるはず

■ rebaseについて

  • localのブランチの派生元をmasterの別のコミットに変更する機能。普通はPRの確認中にmasterが更新されて、コンフリクトが発生したときや、master側の更新を取り込みたい場合に使う
  • localに取り込んだ最新版のmasterを使ってファイル比較、更新をするので、まず取り込みたい更新をlocalに持ってくる必要がある
  • もとのブランチ上にあったコミットは一度破棄され、新たに再作成される
  • 再作成の過程で、コミットごとにコンフリクトが発生したファイルについては再度修正を強要される。
//localのmasterを最新化する
git checkout master && git fetch upstream && git reset --hard upstream/master && git push origin master

//対象ブランチに移動して、rebase開始
git checkout hoge
git rebase master

//コミットごとにコンフリクト情報が表示され、再編集を強制される。コンフリクトがない場合、そのままrebaseは完了する
//修正が完了したら、add、確認、rebase継続
git add -u
git status
git rebase --continue
//コンフリクトを修正したファイルのコミットのためにコメントを要求される

//必要回数繰り返す。不要な更新はskipすることもできる
//successが表示されたら、originにpushする。すでにPRを上げている場合は、-forceオプションを付けないと、pushできない
git push -f origin hoge

■過去のコミットのコメントを修正する

  • 最新のコミットのコメントを修正するのは簡単
git commit --amend -m "正しいコミットコメント"
  • 過去のコミットコメントを修正するのは、対象のコミットのコメントを修正して、それ以降のコミットをrebaseで適用することになるので、古いコミットの場合は大変なことになる
//まずは修正死体コメントを探す
git log | grep hoge
caf173eb hogehoge
485fllws これはhogeです
 :

//対象のコミットを指定してrebase開始
git rebase -i <commitid>
pick caf173eb hogehoge
pick jenv84mn 関係ないコミット
pick 485fllws これはhogeです
  :
//関係ないコミットを含めて、コミットのリストが提示されるので、修正したいコミットの冒頭の「pick」を「edit」に変更して保存する
//edit以外について自動でrebaseする形で処理が開始される
//edit指定したコミットに到達すると、処理が一時停止しするので、git commit --amend コマンドでコメントを修正
//修正したら、git rebase --continueで処理を継続する。
//git rebase --skipで処理をスキップすることもできる(結果がどうなるかはわからない)
//途中コンフリクトなど、自動でrebaseできないコミットが発生すると、処理が停止する
  • ただ単に更新を重ねているはずなのだが、かなりの確率でconflictが発生する
  • 場合にもよるが、通常のコンフリクトと同様に、ファイルを正しくしなくてはいけない
//特定のコミットのファイルで上書きする
git show [HEAD|commit id]:<ファイル名> > <ファイル名>
//更新したら、addする
git add <ファイル名>
git rebase --continue
//メッセージを書くvimが開くので、特に追加記載がなければそのまま保存すると先に進む

//fileのリネームなどで削除されているケースも有る
git rm <ファイル名>
//この場合は自動的にaddされるので、addはいらない

■ リポジトリ上のファイルを完全に削除する

  • https://git-scm.com/docs/git-filter-branch
  • passwordファイルなどを誤ってコミットした場合、履歴も含めて削除する必要がある
  • filter-branchコマンドはlocalのすべてのブランチを対象に処理するため、試すときは別途cloneして実行してみる
  • コマンドはリポジトリのrootで打つ必要がある
  • 複数回実行した場合、前回のバックアップが残っているので --forceオプションを付けないとコマンドが実行できないかも
git filter-branch --tree-filter 'rm -f <削除するファイルの相対パス>' HEAD --all
//または
git filter-branch --tree-filter 'git rm -rf --cached --ignore-unmatch <削除するファイルの相対パス>' --prune-empty -- --all
//ファイル指定は pkg/*.go などワイルドカード指定OK
//git rmの場合は一旦ローカルのファイルは消されないので改めて削除する必要がある
rm -rf <削除するファイルのパス>

git reflog expire --expir=now --all

//localに残っているオブジェクトを削除
git gc --aggressive --prune=now

//対象のファイル履歴が残っているか?
git log -- <削除したファイルのパス>

//コミットの対象になっているファイルの一覧
git show --pretty="" --name-only <commitID>

//コミットに含まれるファイルの表示
git show <commitID>:<ファイルのパス>
//grep
git grep <検索文字列>

//remoteにpushする
git push --force upstream master

■ 他のブランチから、履歴を伴わず更新を取得する

  • git restore を使う
  • 参照元ブランチでindexに入っているファイルのみが対象となる。(当然)削除されているファイルがあると、削除される
//全てのファイルを取得する場合
git restore --source <ブランチ名> .

//ファイルを指定する場合
git restore --source <ブランチ名> hello.c

//ディレクトリを指定する場合
git restore --source <ブランチ名> directory/

//このコマンドはカレントブランチのindexを更新しないので、git statusで確認の上、add & commitが必要
git status
git add .....
⚠️ **GitHub.com Fallback** ⚠️