2017年07月21日

git リモートでの操作

リモートリポジトリの操作のために、まずはローカルリポジトリとの関係を整理する。

git_remote01.png
リポジトリファイルやディレクトリの履歴を管理する場所。
ローカルリポジトリ各ユーザごとに、自分のマシン上に配置するリポジトリ。
リモートリポジトリローカルリポジトリとは別の領域に配置されるリポジトリ。複数人で作業する場合、共有マシンやインターネット上に配置されることが多い。ローカルリポジトリに対して異なるマシンである必要はなく、同一マシン上にあってもよい。デフォルトで "origin" と名称がつけられる。
作業ツリーgit管理下に置かれた、実際に作業を行うディレクトリ。
ローカルブランチ作業ツリーと結びついているブランチ。checkout を行うことで作業するブランチを切り替え、作業ツリーの内容を切り替える。
masterブランチ最初にコミットすると作成されるブランチ。デフォルトで "master" と名称がつけられる。
リモートブランチリモートリポジトリ上のブランチを参照するブランチ。『リモート追跡ブランチ』とも言う。
リモート追跡ブランチローカルリポジトリ内にあり、リモートブランチの状態を保持するポインタ。"origin/master" というのは、"origin" というリモートリポジトリにある "master" ブランチを追跡していることを示す。
追跡ブランチリモート追跡ブランチからローカルブランチに checkout すると自動的に作成されるブランチ。リモートリポジトリのブランチと直接のつながりを持つローカルブランチ。
上流ブランチupstream branch。『追跡ブランチ』が追跡するブランチのこと。

参考:

『リモートブランチ』について
「Pro Git Book(日本語訳)」は『リモートブランチ』と『リモートリポジトリにあるブランチ』を両方、『リモートブランチ』として混在して記述しているのではないかと思う。非常に混乱したが「Pro Git Book」の原文や図などから
『リモートブランチ』=『リモート追跡ブランチ』で解釈した。






リモートリポジトリの複製


他メンバーと作業を共有するためにはリモートリポジトリが必要。リモートリポジトリを使うためにはローカルリポジトリに clone する。

$ git clone <リモートリポジトリの場所>


リモートリポジトリの場所は、http,httpsや、SSHプロトコル、同一マシンであればディレクトリパスを指定する。

リモートリポジトリを clone したら、自動的に "master" ブランチを作成し、"origin/master" を追跡するようになる。



ローカルとリモート(リモート追跡ブランチ)両方のブランチ一覧を確認する。
-a オプションを使う。

$ git branch -a

* master
remotes/origin/HEAD -> origin/master
remotes/origin/master

リモートリポジトリを区別するために、"remotes/" が頭に付く。
"remotes/origin/HEAD" は、リモートリポジトリの現在の "HEAD" が存在するブランチを指す。



orign/master ブランチ以外のブランチを複製


git clone では "master" ブランチしかローカルに複製されていない。
他のブランチを確認するには、-r オプションを使う。

$ git branch -r

  origin/HEAD -> origin/master
origin/master
origin/new_branch

確認できたら、追跡ブランチを作れば良い。-b オプションを使う。

$ git checkout -b new_branch origin/new_branch



ローカルリポジトリのブランチを確認してみる。
 git branch -a
master
* new_branch
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/new_branch







ローカルリポジトリの変更を反映


ローカルリポジトリにコミットされた内容を他メンバーへ公開するために、ローカルリポジトリの内容をリモートリポジトリへ反映する。

$ git push <リモートリポジトリ> <ローカルのブランチ名>



試しに git push を引数無しで実行してみる。

$ git push


リモートリポジトリへ反映はできたようだが、警告が出た。
warning: push.default is unset; its implicit value has changed in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the traditional behavior, use:

git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

git config --global push.default simple

When push.default is set to 'matching', git will push local branches
to the remote branches that already exist with the same name.

Since Git 2.0, Git defaults to the more conservative 'simple'
behavior, which only pushes the current branch to the corresponding
remote branch that 'git pull' uses to update the current branch.

See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)

この意味は、git push を引数無しで実行したことによる警告。

git push を引数無しで実行したときの動作が push.default が指定されていないため警告がでている。また、Git 2.0 以降では matching から simple にデフォルトが変わったと教えてくれている。

この警告を表示させないようにするためには、push.default の設定を追加すればよい。
Defines the action git push should take if no refspec is explicitly given. Different values are well-suited for specific workflows; for instance, in a purely central workflow (i.e. the fetch source is equal to the push destination), upstream is probably what you want. Possible values are:

  • nothing - do not push anything (error out) unless a refspec is explicitly given. This is primarily meant for people who want to avoid mistakes by always being explicit.


  • current - push the current branch to update a branch with the same name on the receiving end. Works in both central and non-central workflows.


  • upstream - push the current branch back to the branch whose changes are usually integrated into the current branch (which is called @{upstream}). This mode only makes sense if you are pushing to the same repository you would normally pull from (i.e. central workflow).


  • tracking - This is a deprecated synonym for upstream.


  • simple - in centralized workflow, work like upstream with an added safety to refuse to push if the upstream branch’s name is different from the local one.

    When pushing to a remote that is different from the remote you normally pull from, work as current. This is the safest option and is suited for beginners.

    This mode has become the default in Git 2.0.


  • matching - push all branches having the same name on both ends. This makes the repository you are pushing to remember the set of branches that will be pushed out (e.g. if you always push maint and master there and no other branches, the repository you push to will have these two branches, and your local maint and master will be pushed there).


To use this mode effectively, you have to make sure all the branches you would push out are ready to be pushed out before running git push, as the whole point of this mode is to allow you to push all of the branches in one go. If you usually finish work on only one branch and push out the result, while other branches are unfinished, this mode is not for you. Also this mode is not suitable for pushing into a shared central repository, as other people may add new branches there, or update the tip of existing branches outside your control.

This used to be the default, but not since Git 2.0 (simple is the new default).
引用:git help config

simple現在のブランチを "upstream branch" に push する。ただし "upstream branch" 名が現在のブランチと異なる場合は push しない。
Git 2.0 でデフォルトとなった。
matchingローカルとリモートで同一名称のブランチに全て push する。いままでのデフォルト。
nothing引数が省略された場合は push しない。
upstream現在のブランチに "upstream branch" が設定されている場合に push する。ブランチ名が異なっていても push する。
current現在のブランチをリモートの同一名称のブランチに push する。"upstream branch" が設定されていなくても push される。


git push 操作には、安全性と効率を考えて simple を設定しておく。

$ git config --global push.default simple






ここで、新しいブランチ "new_branch" を作り、リモートリポジトリへ反映してみる。
$ git push origin new_branch

$ git branch -a
master
* new_branch
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/new_branch

新たにリモート追跡ブランチ "remotes/origin/new_branch" が現れた。



さらに、上流ブランチと追跡ブランチの関係を見てみる。
-vv オプションを使う。

$ git branch -vv

  master     18ccb33 [origin/master] master 追加 3
* new_branch 6fd4bd7 new_branch 追加 1

"master" ブランチに対しては、上流ブランチ(upstream branch) "origin/master" が設定されているが、先ほど作った "new_branch" ブランチには、上流ブランチが設定されていない。



この状態で、"new_branch" ブランチを更新し、再度 push する。
ただし、次は引数無しで push してみる。
$ git push
fatal: The current branch new_branch has no upstream branch.
To push the current branch and set the remote as upstream, use

git push --set-upstream origin new_branch

push.defaultsimple を設定したので、上流ブランチが設定されていない "new_branch" ブランチでは、引数無しの push 操作ができないため警告がでている。


"new_branch" ブランチは、リモート追跡ブランチから checkout したものではなく、ローカルで準備したブランチのため、追跡ブランチにはなっていない。追跡ブランチとして使うためには、上流ブランチを設定すれば良い。

$ git branch --set-upstream-to=origin/new_branch new_branch

$ git branch -vv
master 18ccb33 [origin/master] master 追加 3
* new_branch 6fd4bd7 [origin/new_branch] new_branch 追加 1

上流ブランチが設定できたことがわかる。
これで push を引数無しでも実行できるようになった。


上流ブランチを設定する別のやり方もある。
push するときに合わせて指定すれば良い。
-u オプションを使う。

$ git push -u origin new_branch








リモートリポジトリの履歴取得


複数人で作業していると、リモートリポジトリは他メンバーによって、どんどん更新されていく。ローカルリポジトリも最新履歴を取り込む必要がある。
リモートリポジトリの最新履歴をローカルリポジトリに持ってくる操作が fetch

$ git fetch origin


fetch で更新されるのは、リモート追跡ブランチまで。
ローカルブランチはまだ更新されない。

git_remote02.png

リモートリポジトリの履歴をローカルブランチへ反映するためには、マージすればよい。
"master" ブランチへマージするために、"checkout" してから実行する。

$ git merge origin/master








リモートリポジトリの履歴反映


git fetch + git merge することで、リモートリポジトリから履歴を取得し、ローカルブランチへ反映した。
これをまとめて実行するのが、git pull 操作。

$ git pull origin master


ローカルブランチでの作業の区切りが悪い状態で実行してしまうと面倒なことになる。
なので、git pull は使わなくてもいい。git fetch + git merge で事が足りる。

操作が増えるほうが面倒だと思うかもしれないが、良くわからず git pull を実行したことでローカルブランチが大変なことになるぐらいなら、確実に操作できるほうが良い。

リモートリポジトリ、ローカルブランチ、リモート追跡ブランチなどの関係性が整理できていれば、「このタイミングであれば、まとめて実行したほうが楽。だから git pull を使っても大丈夫」だとわかる。それでなければ git pull を使わないほうが安全。





リモートリポジトリからのブランチ削除


役目を終えたローカルブランチを削除するには、-d オプションを使って、

$ git branch -d new_branch



リモートリポジトリに push されているのであれば、リモートリポジトのブランチも削除する。

$ git push origin :new_branch


この操作の意味を解説すると、
push 操作は、次のように、
$ git push origin new_branch

と、<リモートリポジトリ> <ローカルブランチ名> を指定するが、これは push する先のリモートリポジトリ側のブランチ名が省略されている。ローカル、リモートともに "new_branch" ブランチを指定したということで省略されている。

git push は、本来、次のコマンドのように :(コロン)を使って、リモートのブランチを指定する。

$ git push <リモートリポジトリ> <ローカルブランチ名>:<リモートのブランチ名>




話を戻して、リモートブランチの削除する操作は、git push origin :new_branch

これは push するローカルのブランチが指定されていない →「何もないブランチ」を「リモートのブランチ」へ push する → 「存在しない状態に更新」ということになり、ブランチが削除できる。


次のようにして削除することもできる。
こちらのほうが明示的に削除を指定するのでわかり易い。

$ git push --delete origin new_branch








まとめ


複数人で作業するときはリモートリポジトリが必要となる。リモートリポジトリとローカルリポジトリの関係性が理解できていれば、どのようにデータが更新されるのか理解できるので、コンフリクトしても焦らず対応できる。
git push の逆にあたる操作は、git pull ではなく、git fetch 。"push" の反対なので "pull" だと思ってしまうが、"pull" はローカルブランチに影響を与えてしてしまう操作だが、"push"・"fetch" ともローカルブランチに影響を与えない操作。
今回、リモートとローカルリポジトリの関係性を理解できたことで、今後のリモート操作が安心してできる。



gitをインストール
gitサーバーのセットアップ
git ブランチについて
git 変更を一時的に退避 stash
git ブランチを合流するマージ
git ブランチを付け替える
git コミット履歴を変更する
git 変更をリセットする
git ファイルの追跡
git リリース準備
git リモートブランチを追加
git チェックアウトをもっと便利に使う
git プロジェクトの構成
git 変更をpatchファイルにする
git コンフリクトに対処する
git 失敗したときの復元
posted by Zorinos at 20:00| Comment(0) | Linux | 更新情報をチェックする
この記事へのコメント
コメントを書く
コチラをクリックしてください