git push -u origin featureB:featureBee # featureBブランチを、featureBeeにpushする。 # また -u があるのでfeatureBはfeatureBeeを追跡するように設定する。
$ git checkout 17004ca detached HEADになる。ソース修正やコンパイルなどが可能である。 $ git commit -a -m 'a commit of the detached head of 17004ca' $ git branch fwd_17004ca b815d77 リポジトリにも変更したブランチをpushするには、 $ git push --set-upstream origin fwd_17004ca なお、その後、他のローカル側でこのブランチを利用するには次のようにする。 $ git fetch $ git checkout --track origin/fwd_17004ca
git log --oneline --decorate --graph --all hoge.c gitk --all hoge.c git log --cc --all -S'strings' hoge.c
localな設定 git config --local core.quotepath false #.git/configに保存される git config --local --unset core.quotepath #設定を元に戻す globalな設定 git config --global core.quotepath false #~/.gitconfigに保存される git config --global --unset core.quotepath
git diff eaad7c8 ^254b87b ^d3087fd #changes when merging git diff -U10 eaad7c8 ^254b87b ^d3087fd #changes when merging 違いが出るのはなぜか?
こちらへ howto/git/forthefirsttime
https://git-scm.com/book/ja/v2
ここからダウンロード(2021/04/15)したPDF版のファイル (ただしそのままでは不具合があるようだったので、macOSのプレビューで開いてから再度PDFで保存し作成した)。 2nd Edition (2014) のファイルです。 なお、旧版はDownloadsメニューにあるらしい。
このPDFは Scott Chacon and Ben Straubにより書かれたものであり、 ライセンスは CC BY-NC-SA 3.0です。
以下は古いもの。
例) find . -type d -empty -not -path './.git*' -exec touch {}\/.gitkeep \;
git add . # カレント以下のファイル(ディレクトリ含む)をステージに追加する git add ファイル # ファイルをステージに追加する git add -u # 追跡対象のファイルで修正があったものをステージに追加する
git mv 変更前のファイル名 変更後のファイル名 mv 変更前のファイル名 変更後のファイル名 git add -u git add 変更後のファイル名 としても良い。 mv hoge.out hoge.out.chked git add hoge.out.chked をした。 リポジトリにある hoge.outを削除したいとき、 git add hoge.out をするとよい。
git rm [--cached] 削除ファイル # --cachedがあるとステージからも削除し、追跡対象からはずす。 # 間違ってaddしたファイルをステージだけからいったん削除したいときは、 # git reset HEAD file を使う(説明を参照のこと)。 作業ディレクトリでファイル hoge.outを削除した。 リポジトリからも削除したいとき git add hoge.out すればよい。
コミット済みのファイルfile.cを $ git rm file.c として、ステージが deleted: file.c となっている状態で、やっぱり削除を取り消すときは $ git checkout -- file をする。
git update-index --skip-worktree ファイル名 # 指定した作業領域上のファイルの変更を、維持するように登録する # (マージしても変更されなく、維持される) git update-index --no-skip-worktree ファイル名 # 上記の登録を解除する git ls-files -v | grep ^S # skip-worktreeしたファイルを確認する
git ls-files -o #カレントディレクトリ以下で、追跡されていないファイルのリストを表示 git ls-files -o --exclude-standard #git ls-files -o のうち、.gitignoreで無視したファイルを除くリスト
⇒ むずかしいのでほどほどで対応すればよい。
⇒ コミットメッセージは英語でする。日本語は使わないこと。
git config --global user.name "yourname" # 実行すると ~/.gitconfigに保存される git config --global user.email "youremail" # --global無しだとリポジトリ毎の.git/configに保存される git config --global core.editor emacs git config --global push.default simple # simple(デフォルト)、matching(2.0以前のデフォルト) git config --global credential.helper 'cache --timeout=1800' # 数分間だけ認証をキャッシュする。 #httpsのみ?sshのヘルパーを動かす?
git commit -m 注釈 # ステージ済みをコミットする git commit -a -m 注釈 # 追跡対象(のみ!)をステージしてコミットする git commit --amend -m 注釈 # push前の直前のコミットを上書きする(直前のコミットをやり直せる)。 push後にすると、両者のmergeが必要となるのでしないこと。 なお、-m 注釈 無しだと、エディタが立ち上がる。
git checkout -- file # fileをチェックアウトの時点にもどす(fileの修正箇所は削除される元に戻る!) git reset HEAD file # ステージにあるfileを取り除く。そのfileは作業ディレクトリに移動する(マージされるようだ)。 git reset --hard # 現在のブランチを、チェックアウトの時点まで取り消す(修正中ファイルは削除される!)
git merge [リモートリポジトリ/]ブランチ # 現在のブランチに、指定のブランチをマージ # 競合発生の場合は解決する 例)masterブランチを修正してcommitした。pushしようとしたが、リモートのmasterブランチが 変更されていたためrejectされた。その場合、 $ git fetch $ git merge origin/master $ git push とする。
$ git merge --no-commit --no-ff [リモートリポジトリ/]ブランチ #コミットしない、fast forwardでもコミットしない。 マージされた結果はステージにのるので、 $ git diff --cached で結果を確認できる。(コンフリクトしていたらその旨が出る。) (a) このマージを取り消したければ、 $ git merge --abort をする。 (b) そのままコミットしたければ git commit する。git merge --abort 後に git merge [リモートリポジトリ/]ブランチ をしてもよい。
(実例)作業領域に更新があり、コミットしていなく、したくないが、リモートリポジトリの更新を pullしたいとき $ git stash $ git pull $ git stash pop # popする(applyして、リストからは削除) で良いらしい。 --skip-worktreeしたファイルがコンフリクトしていた場合は、コンフリクトのためAbortするので、 --no-skip-worktreeしてから git stashする。 git stash [ save [--include-untracked]or?[--all] ["メッセージ(日付を入れると良い)"] ] git stash list git stash apply --index [ stash@{0} ] #auto mergeなどされるようだ。 git stash drop stash@{0} #削除 git stash pop #変更をpopする(リストからは自動で削除される。コンフリクトがあると削除されない) 今の作業ブランチにapplyやpopがされるようだ。 logをみると stashしたものの SHA1がわかるので、ブランチ名をつけて作業してゆくこともできる。
単純なコンフリクトの場合は、ファイルにコンフリクトの内容が、 <<<<<<< HEAD ほげほげ ======= ほげほげ >>>>>>> SHA1 と書き込まれているので、エディタで修正して、保存する。その後、 $ git add ファイル $ git commit -m '注釈' をすれば良い。
コンフリクトしたとき git show :1:ファイル名 > ファイル名.common git show :2:ファイル名 > ファイル名.ours git show :3:ファイル名 > ファイル名.theirs 作業後、 git merge-file -p ファイル名.{common,ours,theirs} > ファイル名 または git checkout --conflict=diff3 ファイル名 #ファイル名のファイルを再度チェックアウトし、diff3でコンフリクトマーカー作り直す
git clean -n で確認して git clean -f で追跡対象以外(無視するファイルは除く)を 削除できる。(カレントディレクトリのみ対象にしたいときは-dを付ける。 無視するファイルも消す?ときは-xを付ける。対話的に消したいときは-iを付ける?)
+------>o fixブランチ | ------>o masterブランチ | +------------->o----> 作業ブランチ ~~~~~ 未コミット部分A o 印はコミット ブランチの分岐が上図のようにあり、 作業ディレクトリのブランチに fixブランチをマージするには、 次の(1)-(4)のいずれかの方法でできる。 作業ブランチをコミット済みの状態にしておき、(2)の方法でコミット するのがいちばん素直だろう。 (fixがmasterの進んだコミットであっても同じ) (1) git merge origin/fix これは自動的にコミットされる。 たぶんA部分があればエラーとなる? もしくは、A部分もコミットされる? fixに関係 するファイルだけか? コンフリクトしたら作業ディレクトリのファイルにその内容が入る。 (2) git merge --no-commit --no-ff origin/fix 自動的にコミットしない。 コンフリクトしたら作業ディレクトリのファイルにその内容が入る。 確認後、 git merge --abort で取り消すか(取り消してから(1)でマージしてもよい)、または、 コンフリクトがあれば修正して(無ければそのままで)、 git commit -m "hogehoge" する。 (なお、コミットする前にはコミットするファイルを取捨選択もできる)。 (3) git cherry-pick SHA1 fixのコミットのSHA1をマージする。master--->fixの間に複数のコミット があれば順に全てに対してこのコマンドでマージする。 たぶんコンフリクトしたら作業ディレクトリにその内容が入る。 (4) git stash --skip-worktreeしたファイルは無いことが望ましい。 git merge origin/fix をする(または (1)-(3)のいずれかでもよい)。 git stash pop たしか、コンフリクトしたら作業ディレクトリのファイルにその内容が入る。 そして stashは消されずに残る。
git status [-s] # -sは簡潔表示であり、gitで管理していないファイルは「?? ファイル名」で表示される。 git diff [ファイル] # 作業ディレクトリとステージの比較(ステージにファイルが無ければコミット済みと比較される) git diff --cached [ファイル] # ステージとコミット済みの比較 git diff A B # 差分をみる。AやBは SHA1[:ファイル]|タグ git diff A..B # 〃 git diff A...B # AとBとの共通の親と, Bの差分 git diff master..origin/master # リモートリポジトリ(origin/master)との差分をみる(fetch済みであること)
git diff -w # ファイル内のスペースの違いを無視、改行コードの違いも無視 git diff -b # ファイル内のスペースの数の違いを無視、改行コードの違いも無視 git diff --name-only # ファイル名だけを比較する # 削除されたファイルは表示されないようだ(git diffをすると詳細がわかる) git diff --name-status # ファイル名だけでなく、変更か追加か削除かも表示
git diff コミット名1 コミット名2 -- ファイル名 # 両方のコミットで、ファイルを比較 git diff コミット名1:ファイル名1 コミット名2:ファイル名2 # 各コミットのファイルを比較 git show オブジェクト[:ファイル] # SHA1で指定したオブジェクト(コミット、ツリー、ファイル)を表示する。 # :ファイル で限定もできる。
git log -5 --oneline --decorate --graph --all [--stat] [-p] # --graphにより図形表示される # --author=パタン でuser.nameの選択ができる # --decorateによりHEADの位置がわかる # -pはソースの差分が出る。 # --statはサマリーが出る。 # -5は 5件だけ表示 git log --since="50 minutes ago" [ファイル名] # 50分前からのログのみ表示 git log --no-merges issue54..origin/master #ログのフィルター記法 #origin/masterには含まれるが、issue54には含まれないコミットのログだけを表示 git log contrib --not master # masterに無くcontribブランチにあるコミットのログを表示
git log -p -S'hogehoge' file # コミットの中で、fileのhogehogeを含む行が追加or削除された # コミットを表示する。-pオプションがあるのでそのコミット時の # diffも表示する。
git log --cc --all -S"h5py.get_config().default_file_mode = 'a'" misc.py --ccで各コミットのdiff(実際はパッチ)をとる(マージコミットも対象とするために -pでない方がよい) -Sで検索にヒットしたコミットだけ表示する コミットのSHA1やコミットメッセージがわかるので、 git show 287658 や、 gitkの Find欄にそのメッセージを入れて、コミットを検索表示できる(gitkだと親や子のSHA1がわかる)
log -p や --cc の例
/bin/rm -rf .git a b git init echo foo > a; git add a; git commit -m "add a" git branch other; git checkout other echo bar > b; git add b; git commit -m "add b" git checkout master git merge --no-commit --no-ff other echo bart > a; git add a git commit -m "merge branch other" echo "*** log"; git log -25 --oneline --decorate --graph --all echo "*** log -p"; git log -p echo "*** log --cc"; git log --cc
git blame [-C] -L n,m file # fileに対して、n~m行目の最後のコミットをリストアップする # -Cがあると別の所からのコピーがあれば示してくれる # 行は1から数える。 その他 gitに bisectというものもあり(二分探索によるデバッグ支援)。 git log -p -S も見よ。
git blame -C -L 141,153 ファイル名 #ファイル名のファイル 141から153行目を対象に別の所からコピーされたコード片を探す
$ git blame -C -L 1,1 nameless_cfemns.h 86e41aa4 (okazaki,i 2018-04-01 17:37:31 +0900 1) /* nameless_cfemns.h */ $ git blame -C -L 23,23 makefile 1e84d5f5 (okazaki,i 2018-03-19 20:13:09 +0900 23) DOPT = -Ofast
git grep --heading --line-number -3 'readGrid' # ファイル名を先頭に、行番号を行頭に、検索文字列の前後各3行、をマッチしたもの # について表示する git grep -w 文字列 # 単語境界での検索 -F # 正規表現を利用しない -l # マッチしたファイル名だけ表示 # 作業領域で追跡対象のファイルを対象に検索が行われる。 $ git grep -l 文字列 | xargs sed -i '' -e 's/文字列/置換文字列/g' # なお、-iが空でなければその拡張子でバックアップが作られるらしい。 git rev-list {--all|ブランチ名} | xargs git grep '文字列' #すべてのブランチか、指定したブランチについて、検索が行われる。
git grep 文字列 [タグ|SHA1] # 該当プロジェクトで文字列検索
git rev-list --all | xargs git grep --heading --line-number -10 'rs+1'
git branch -a #ローカルにある◯/◯のリモートブランチと、ローカルリポジトリのブランチをすべて表示 git branch ブランチ # ブランチを作成 git branch -vv # ブランチを表示 git branch -m 古いブランチ名 新しいブランチ名 #ブランチ名を変更する git branch -m 新しいブランチ名 #現在のブランチ名を変更する git branch -d ブランチ # ブランチを削除(ローカルのブランチ)
リモートリポジトリのブランチを削除し、ローカルのブランチも削除する git push origin --delete nwp2 または git push origin :nwp2 または git push origin :refs/heads/nwp2 次に、git fetch する(ローカルにあるその◯/◯のリモートブランチも自動で削除される)。 (備考) ・pullやcloneされた別のリポジトリでは、その人が消さない限りそのまま残る。消されたリモートブランチを もつその人は、pushするとリモートリポジトリのブランチは再度作られる。 ・detached branch(ブランチ名の付いていないブランチのようなもの)は、git logには出てこない。リポジトリに 残っていると思うが、どのように検索できるのか? ローカルにある◯/◯のリモートブランチを削除する(あまり使わないだろう) git branch -d -r originfuji/masterfuji #-dの代わりに -Dとするとマージしていなくても削除する (リモートにあるそのリモートブランチが削除されていなければ、fetchすると再度、〇/〇は作成される)
git branch --merged # 現在作業中のブランチにマージされたブランチのリストを表示 git branch --no-merged # 現在作業中のブランチにマージされていないブランチのリストを表示
git branch ブランチ1 リモートリポジトリ/ブランチ2 # リモートリポジトリ/ブランチ2を追跡 # するブランチ1を作る git branch --set-upstream=リモートリポジトリ/ブランチ2 ブランチ1 # リモートリポジトリのブランチ2を追跡 # するようにブランチ1を設定する --set-upstream の省略形は -u である。
git fetch --all # 登録されている全てのリモートリポジトリから最新情報を取得する git fetch --tags # リモートリポジトリにあるタグも取得する git fetch [リモートリポジトリ] [ブランチ] # リモートリポジトリから最新情報を取得する git pull [リモートリポジトリ] # fetchし、mergeする(pull=fetch+mergeに相当) git push [リモートリポジトリ] [ブランチ] [--tags] # 競合が発生した場合は pushはできない(pullして競合解決してから pushする)。 # --tagsはタグもプッシュする
git tag # すべてのタグを表示 git tag [-a] タグ [SHA1ハッシュ] [-m 注釈] # タグを付ける(-aと-mで1行の注釈を入れれる。-aのみは注釈を入れるために # エディタが立ち上がる) # -sオプションで署名もできるらしい(詳しくは https://git-scm.com/book/ja/v2 の5章) git tag -d タグ名 #タグ名を削除する git show タグ名 #タグ名の情報を表示 git fetch --tags #リモートリポジトリのタグを取得する
git push --tags #リモートリポジトリに無いタグを、全て送る git push --delete リポジトリ タグ名 #リポジトリ(originなど)のタグ名を削除
git checkout {SHA1|タグ|masterなど} # 指定のものをチェックアウトする。 # ブランチ名(masterなど)ではなく、SHA1(ハッシュ値)を指定した時、detached HEADになるが、 # 普通どおり修正してコミットできる(ブランチ名を新たにつける方が取り扱いやすい)。 # 追跡対象外のファイルなどは、そのまま残される。
git checkout --track リモートリポジトリ/ブランチ # git checkout -b ブランチ リモートリポジトリ/ブランチ と同じ。 # 作成されたブランチはリモートブランチ(追跡ブランチ、上流ブランチ)を追跡するように設定される。
git checkout -b ブランチ {タグ|リモートリポジトリ/ブランチ} # -bで指定するブランチを作成後、移動する。 # タグがあれば、その所にブランチを作る(ただしコミットするとブランチは進む。タグは動かない)。
gitk # GUIツール
git help コマンド名
git diff差分はそのままでパッチファイルになっている。 また、パッチファイルを使って、リダイレクションでパッチをあてることが出来る。 patch [--dry-run] -p1 < パッチファイル #パッチファイルをあてる場合 #--dry-runは何が行われるかを表示するだけ。
git config [--global] -l # .git/configを表示 git config [--global] -e # .git/configを編集
HEAD # 現在作業中のローカルブランチを示す
git archive master --prefix='project/' --format-zip > git_master.zip
git shortlog --no-merges master --not hogehoge #masterブランチに対してタグhogehogeからのコミットログを出力する
tagを消すとき git push origin :refs/tags/タグ名 branchを消すとき git push origin :refs/heads/ブランチ名
まず、ブラウザで名前を付けてリポジトリを作る。 ここへのpushの仕方が表示されるので、ローカルに作っておいたリポジトリをpushする。
$ git push (gnome-ssh-askpass:hogehoge): Gtk-WARNING **: cannot open display: error: unable to read askpass response from '/usr/libexec/openssh/gnome-ssh-askpass' Username for 'https://github.com': などと、表示される場合の対応。 - 無視して、つづけて問題無い。 (GUI環境で無いために、パスワードキャッシュがうまく動かなかったらしい) - unset SSH_ASKPASS をすると表示されなくなる。
作業領域やステージはcommit,push済であるとする。 $ git branch nwp # 現在の状態で、ブランチnwpを作成 $ git checkout nwp # ブランチnwpに移動(作業ディレクトリのファイルは同じものである) なお、ここでaddやcommitをしても良い。 $ git push --set-upstream origin nwp # リモートリポジトリoriginのブランチnwp(作成される)にpushする。 # ブランチnwpは、origin/nwpを追跡するように設定される(オプション # --set-upstreamによる)。 $ git remote -v ; git branch -vv # 確認
作業領域やステージはcommit,push済であるとする。 $ git fetch $ git checkout --track origin/nwp $ git remote -v ; git branch -vv # 確認
git checkout --track origin/sotu_p git checkout sotu_p git push originfuji sotu_p git checkout -b sotu_pfuji originfuji/sotu_p
「originfuji/masterをorigin/masterにマージする仕方」 masterブランチに限らなく、masterの代わりに適当なブランチ名でも利用可能。 必要に応じて、最初だけすること git remote add originfuji fujiのベアリポジトリURL git fetch originfuji git checkout -b masterfuji originfuji/master #originfuji/masterを追うブランチmasterfujiの作成 git checkout master #origin/masterをチェックアウト git merge masterfuji #masterfuji(これはoriginfuji/master)をmasterにマージする。 #masterfujiブランチを作っていなくても、 # git merge originfuji/master でも可能。 #Fast-forwardの場合はコミットされずに更新されるので、 #必要に応じて --no-commit --no-ff をつける。 git push #origin/masterにプッシュ
「その他参考」 リモートリポジトリに無いブランチをpushする例 master 8ed9219 [origin/master] Merge branch 'master' into HEAD masterfuji 8ed9219 [originfuji/master: ahead 3] Merge branch 'master' into HEAD があり、今使っているブランチが masterfujiであり、pushしたいとして、git pushしたとする。 ブランチが、リモートリポジトリに無い(masterfuji?)ときに git push すると、サゼッションが出る。それに従うとよい。すなわち、 リモートリポジトリの masterとして pushする場合: git push originfuji HEAD:master # HEAD:は無くてもよいらしい リモートリポジトリに今使っているブランチ名で新しく追加する場合: git push [--tags] originfuji masterfuji #このやり方は、現在のブランチをoriginfuji/masterfujiという #ブランチ(新たに作成or更新するようだ)にpushするときにも有効である。 とする。
・作成方法1 cd ディレクトリ.git # 拡張子を慣習的につける git init --bare
・作成方法1(新規作成) cd 作業ディレクトリ git init
・作成方法2(リモートリポジトリのクローン) git clone リモートリポジトリ [作業ディレクトリ] # リモートリポジトリは [ssh://[user@]host.xz[:port]]/path_to_repo.git などのurlで指定する。 # 自動的に、origin という登録名でurlが登録され、リモートブランチ(origin/master)を追跡するブランチ master が作られる。 # 作業ディレクトリを省略すると、リモートリポジトリのディレクトリ名(ディレクトリ名.gitの.gitの前の部分)となる。 # 作業ディレクトリを指定する場合は空ディレクトリでなくてはならない。
リモートリポジトリの移動自体は単にまるごとディレクトリを移動するだけである。 これに追従しているリポジトリは git remote set-url origin 新しいリモートリポジトリ をして、登録名の内容を上書き更新する(originを消してから作り直してもよい)。
git add ファイル git remote add origin リモートリポジトリ # リモートリポジトリを登録名originとして、登録する git remote -v ; git branch -vv git commit -m "注釈" git push --set-upstream origin master # --set-upstreamは現在のプランチの追跡先を、origin/masterとする設定も登録する
git remote add リモートリポジトリの登録名 リモートリポジトリのurl git remote rename リモートリポジトリの変更前の登録名 リモートリポジトリの変更後の登録名 git remote rm 削除するリモートリポジトリの登録名 git remote set-url origin 変更後のリポジトリのURL git remote [-v] # 一覧表示
originリモートリポジトリを変更することができる(例) $ git remote rm origin #登録されているリモートリポジトリを削除 $ git remote add origin ssh://hogehoge/nl.git #別のリモートリポジトリを登録 #このままの状態ではローカルのmastgerはどこも追跡していない(いったん削除したため)。 $ git fetch #最初にまず origin/masterを取り込む $ git branch --set-upstream-to=origin/master #カレントブランチがorigin/masterを追従するための設定 or $ git push --set-upstream origin master #ローカルmasterがorigin/masterを追跡する設定