git add を取り消す(indexから外す)
indexから外すだけで、ファイル自体は何も変更されない。
$ get reset HEAD ファイル名
ファイル削除を取り消す
$ git checkout -f
※他の変更も取り消されるので注意。
コミットを取り消す
★危険性をよく理解した上で実行すること!
★Windowsのコマンドプロンプトで実行する場合、HEAD^の部分を "" で囲んでおかないと正常に動作しない。
※commit だけ取り消し
$ git reset --soft HEAD^
※commit, add 取り消し (デフォルト)
$ git reset --mixed HEAD^
※commit, add を取り消して、ワーキングツリーも一つ前に戻す
$ git reset --hard HEAD^
コミットを2つ以上取り消す場合には HEAD^^
やHEAD~2
のようにする。
但し、リポジトリの最初のコミットだけは上のやり方ではエラーになる。
そんなときは下のやり方で。
$ git update-ref -d HEAD
※参考: gitで最初のコミットを取り消す
コミットの取り消しの取り消し(^^;)
# まずは過去のコミット一覧を見る
$ git reflog
# そこからコミットを選択して復元する
# 例)git reset --hard HEAD@{2}
$ git reset --hard <コミット>
※参考: Gitでやらかした時に使える19個の奥義
マージを中止する
$ git merge --abort
$ git reset --hard HEAD
※参考: 【git】マージしたけどやっぱりやめたい時のやり方3種類 - Qiita
完了したmerge/rebaseを取り消す
注: このやり方で取り消していいのは、まだ他者に取り込まれていない場合だけ。
$ git reset --hard ORIG_HEAD
※参考: Gitでやらかした時に使える19個の奥義
※参考: マージ後の git reset HEAD^ は危険だった - unpushの日記
リポジトリからファイル/ディレクトリをその履歴もろとも完全に削除する【危険】
うっかりprivateな情報をコミットしてしまった場合や、巨大なファイルを入れてしまった場合など、どうしても完全削除しないといけない場合はある。コミットしたばかりなら git reset
すれば事足りるが、やらかした後にいくつものコミットが積み重なってしまった場合、そんなときのために。
準備
共同作業者がいる場合は、必ず事前に了解を取っておく。
- あらかじめ全ての変更をcommit&pushしてもらうこと。必要ならローカルのtag/branchもpushしてもらう。
- 作業終了後にcloneし直しになることも伝えておく。
コマンド
$ git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch send_mail/ word_gen/' --prune-empty -- --all
$ rm -rf .git/refs/original/
$ git reflog expire --expire=now --all
$ git gc --aggressive --prune=now
$ git push origin --all --force
後処理
その後、他のローカルリポジトリをcloneし直す。
共同作業者がいる場合は、全員にcloneし直してもらう。
参考
git最強のオプション filter-branch
git filter-branchで過去の全てのcommitから画像ファイルの追加/変更をなかったことにしてリポジトリを軽量化する
git repository size を削減する
コミットの打ち消し
「取り消し」とは違い、打ち消しコミットを入れる。
既にpushしていて、resetするわけにもいかないような場合にはこれで。
$ git revert dd85d5t
$ git revert 56dc6d9
打ち消したいコミットが複数ある場合は、コミットしたときの逆順で(=最近のコミットから順に)revertしていけばOK。
ブランチを作り忘れた時
ブランチ(working)を作成してcheckoutするだけ。
$ git checkout -b working
既にコミットしてしまっている場合は、もっといろんなことをやらないといけない。
pushするときは -u を付ける。(まだremote側に同名ブランチがないので)
$ git push -u origin working
ブランチを別の作業ディレクトリに取り出す - worktree
例えばfeatureブランチで作業中に、masterブランチをちょこっと修正したいというような時、かつstash&checkoutもメンドクサイ(事情によりやりたくない)というような時、リポジトリをcloneすることなく、現在のlocalリポジトリから別の作業ディレクトリにブランチを取り出せる。
worktreeの作成(branchをworkdirに取り出し)
$ git worktree add <workdir> <branch>
※submoduleが含まれている場合は、addした後に `update -i` が必要
$ cd workdir
$ git submodule update -i
worktreeのリストを表示
$ git worktree list
F:/work/Src/App d75d07d [feature-xxx]
F:/work/Src/AppInitial ab268db [task_xxx]
F:/work/Src/AppMaster 1ada79f [master]
取り出したworktreeがいらなくなったら、まずはディレクトリを普通に削除し、次に以下のコマンドを実行。
$ git worktree prune
別名のブランチをpushする
ローカルの develop-new-feature
ブランチを、リモート(heroku)の master
にpushする例。
$ git push heroku develop-new-feature:master
不要なブランチ(ローカル&リモート)を削除する
参考: gitの不要なブランチを消すコマンド - Qiita
ローカルブランチの削除
# マージ済みブランチを一覧
$ git branch --merged [ブランチ名] ※ブランチ名を省略した場合はカレントブランチ
# ブランチを削除 ※安全のため未マージのブランチは削除出来ないようになっている
$ git branch -d ブランチ名 ※ブランチ名はスペース区切りで複数可
ローカルでのブランチ削除をリモート側に反映
# リモートブランチの最新状況を取得: pオプションによりリモート側のブランチ削除をローカル側に反映させる
$ git fetch -p
# マージ済みリモートブランチ一覧
$ git for-each-ref --sort=committerdate --format='"%(committerdate:short)","%(authorname)","%(refname:short)"' refs/remotes --merged
# リモートブランチを削除
$ git push --delete リモート名 ブランチ名 ※ブランチ名はスペース区切りで複数可
gitで管理しているファイルの一覧表示
$ git ls-files
gitで無視したいファイルが既にリポジトリにあるかを調べる
無視したいファイルがリポジトリにあるか確認して、もしあるなら削除したいと思って調べたメモ。
gitのls-filesサブコマンドで確認できる。
$ git ls-files -i --exclude-standard
さらに削除まで行う。
http://qiita.com/yuuAn/items/b1d1df2e810fd6b92574
$ git rm --cached `git ls-files -i --exclude-standard`
$ git st
$ git ci -m "xxxx"
特定のignoreファイルでignoreするファイルだけを対象にするならこれ。
$ git rm --cached `git ls-files -i --exclude-from=.gitignore`
サブモジュールについて
リポジトリにサブモジュールを追加
$ git submodule add [-b submodule側のブランチ名] //server/share/repo/subdir.git [Path to submodule dir]
$ git submodule update -i
# 親プロジェクトをpullした時にsubmoduleがmodifiedになっていたらsubmodule updateする
$ git submodule update
$ git submodule status
5509...6136 MaterialDesignInXamlToolkit (v1.0-1102-g55099eb)
+9d15...95bc WindowsUtil (xxxxx-g8fo4a8ab)
この例の2番目のsubmoduleのように、行頭に何かマークが付いていたら何らかの問題があるということ。+
の場合は git submodule update
すれば解消すると思う。
プレフィックス | 意味 |
---|---|
- | 未初期化 |
+ | インデックスのSHA-1と合っていない |
U | コンフリクト発生 |
submoduleを解除(削除)
★VisualStudioでsubmoduleのプロジェクトを参照している場合はそれを外しておく。
★さらに、VisualStudioが起動していると git rm が失敗するので、あらかじめVisualStudioを終了しておく。
# submoduleディレクトリの中身もキレイに消えてしまう点に注意
$ git submodule deinit <Path to submodule dir>
$ git rm <Path to submodule dir>
★上記サブモジュールディレクトリ<Path to submodule dir>
自体が残っていたら、それも削除し、コミットする。
※これをやっておかないと、git submoudle update -i
したときにエラーが発生する。
最後に .git/modules/<submodule名>
ディレクトリを手動で削除する。(参考: git submoduleについてのメモ 追加/削除/更新等)
過去のコミットをチェックアウトしたらsubmoduleが見つからないというエラーが発生した場合
NAS名の変更やクラウドサービスの変更などにより、submoduleリポジトリパスが昔と変わってしまっている場合もままあると思われる。このような場合に古いコミットをチェックアウトすると submoduleが見つからない旨のエラーが発生し、正しくチェックアウトできないことがある。1
そのような場合には、手作業で .git/config を編集し、urlの部分を正しい(現在の格納先)URLに変更し、再度チェックアウトする。
[submodule "MaterialDesignInXamlToolkit"]
url = //server/repos/MaterialDesignInXamlToolkit.git
※この後、間違って git submodule sync
してしまうと、.git/config の記述が書き換わってしまうので注意。
参考: 関連するファイルは以下の2つ
ファイル | ソース管理 | url記述 |
---|---|---|
.gitmodules | されている | 当時のURLが記載されている |
.git/config | されていない | 現在参照可能なURLを記述する |
参考
git submodule は癖がすごいとの噂だったが素直につきあっていけそうという話
Git submoduleの抑えておきたい理解ポイントのまとめ - Qiita
場合によっては(みんなのgitリテラシーが高ければ?) submodule よりも subtree の方が向いてるかも
git-subtree移行メモ - Qiita
HEAD detached at xxxxxxxx が発生したら…
VisualStudioでsubmodule側を編集しているといつの間にか HEAD detached at xxxxxxxx
という状態になっていることがある。
> git st
HEAD detached at 6bc06705
nothing to commit, working tree clean
解消方法を手順だけ記載。
> git co -b tmp_branch ※これで変更がちゃんとブランチに紐付く
> git co master ※変更をmasterブランチに取り込む場合
> git merge tmp_branch ※これで変更がmasterに取り込まれた
> git branch -d tmp_branch ※不要なブランチは削除しておく
参考: detached HEAD状態から元に戻すコマンド
関連コマンド: detached HEAD から脱出する方法を git の内部構造から探る - Qiita
リポジトリの特定ディレクトリを別リポジトリにする方法
もちろん、コミット履歴を残したまま。
$ mkdir new_repo
# まず丸ごとclone
$ git clone org_repo new_repo
$ cd new_repo
# proj_a/subdir というディレクトリ(の中身)を最上位ディレクトリに引き上げて、
# それ以外は履歴もろとも全て削除。
# --allを付けることでBranchも上手いことやってくれるらしい
$ git filter-branch --subdirectory-filter proj_a/subdir -- --all
参考
[gitの特定のディレクトリをブランチ毎別リポジトリにする方法]
(http://qiita.com/wataru420/items/f1eb7cf37fe5ba4980c3)
[git の特定ディレクトリをコミットログ等込みで別プロジェクトへ移動]
(http://subtech.g.hatena.ne.jp/secondlife/20101108/1289221814)
bareリポジトリを共有ディスクに置いて中央リポジトリとして複数人で使う
GitHubのようなクラウドソースコード管理が使えるわけでもなく、かといって社内でGitBucketのようなオンプロミス型のGitサーバーを立てるのも面倒…
そんな時、お手軽にNASなどの共有ディスクにgitリポジトリ(bareリポジトリ)を置いて、みんなでpush/pullしても大丈夫か?リポジトリが壊れたりしないか?ということについて調べてみた。
探し方が悪かったのか、なかなかこれといった情報が見つからなかったが、やっと見つけた。
結論としては、『複数人でもちゃんと使える』とのこと。
NAS等の共有ディスク上にbareリポジトリを生成する手順は次項参照。
ローカルのリポジトリをcloneして、bareリポジトリを生成する手順
$ cd ローカルリポジトリ
# リポジトリ名.git というディレクトリが作られて、その中にbareリポジトリができる
$ git clone --bare . //server/share/path/リポジトリ名.git
# originの宛先URLを変更する ※追加の場合は set-url ではなく add
$ git remote set-url origin //server/share/path/リポジトリ名.git
# 確認
$ git remote -v
$ git remote show origin
# 作成したbareリポジトリにのmasterとlocalのmasterを繋げておく ※upstream branch としてセットしておく
$ git push -u origin master
Branch master set up to track remote branch master from origin.
Everything up-to-date
参考: remoteリポジトリを指定する文字列
以下のように file://
を付けて記述してもいいらしいが、データ転送がとても非効率とのこと。
file:////server/share/repo
リポジトリ(作業ディレクトリ)ごとにcommitユーザー(Author)を設定する
$ cd リポジトリ(作業ディレクトリ)のトップ
$ git config user.name "xxxx"
$ git config user.email "xxxx@xxxxx.xxx"
ローカルの .git/config に設定値が書き込まれる。
[user]
name = xxxx
email = xxxx@xxxxx.xxx
確認コマンドはこちら。
$ git config --list
$ git config --list --global
$ git config --list --local
.gitignore の生成
.gitignoreをコマンド一発で生成する。
気付いたら.gitignoreはgiboで自動生成する時代になっていた - Qiita
一度インストールすれば、あとはちょっとしたコマンドを叩くだけ。
# ローカルに保存しているgitignoreのテンプレートをupdate
$ gibo -u
# テンプレートを一覧表示
$ gibo -l
# 生成
$ gibo Ruby Rails JetBrains SublimeText VisualStudioCode Linux macOS Windows >> .gitignore
SourceTreeにリポジトリを追加したら、不意に「Select a credential helper」というメッセージが表示された [Windows10]
「Always use this from now on」にチェックを付けて、2番目の manager を選択すれば、以降何も聞かれなくなった。
その他
-
.git/configに正しいURLが記載されている場合は正しくチェックアウト出来る。 ↩