Gitのリモート絡みの要素について確認してみる

こちらの記事で触れた内容を実際に確認してみるという試み。

https://qiita.com/Crawd/items/63c4a71efecced16d32b


## 手順概要
以下の手順で確認する。
1. 適当なリモートリポジトリを用意する
1. 新規にローカルリポジトリを作成する(`git clone`はしない)
1. `git fetch` `git merge` `git push`をリモートリポジトリに対し、引数なしで正しく実行できるように設定していく

## 実際に確認してみる
まずはローカルリポジトリを作成する。
```
> mkdir test
> cd test
> git init
```

`git fetch`、`git merge`を実行する。
```
> git fetch

> git merge
fatal: No remote for the current branch.
```
リモートが登録されていないと出たので設定する。
リモートリポジトリを`origin`という名前で登録。
```
> git remote add origin git@github.com:test/Repository.git

> git remote -v
origin  git@github.com:test/Repository.git (fetch)
origin  git@github.com:test/Repository.git (push)
```

再度`git fetch`から実行する。
```
> git fetch
remote: Enumerating objects: 19, done.
remote: Counting objects: 100% (19/19), done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 19 (delta 2), reused 12 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (19/19), 3.40 KiB | 34.00 KiB/s, done.
From github.com:test/Repository
 * [new branch]      main       -> origin/main
```
リモートブランチ`main`のリモート追跡ブランチ`origin/main`が作成され、フェッチできた。
リモート名の指定が省略された場合は、`origin`が用いられる。
どこから何を`fetch`するかは`remote.origin.fetch`の値で決定される。

続いて`git merge`してみる。
```
> git merge
fatal: No remote for the current branch.
```
先程と同じエラーが出た。
引数なしの場合、上流ブランチの設定が必要なようなので試みる。
```
> git branch -u origin/main
fatal: branch 'master' does not exist
```
まだ一度もコミットしてないので、`master`ブランチが作成されていない。
適当に空コミットして`master`ブランチを作成する。
```
> git commit --allow-empty -m "init"
[master (root-commit) 8257c52] init
> git branch
* master
```

`master`ブランチが作成できたので、上流ブランチを設定する。
```
> git branch -u origin/main
branch 'master' set up to track 'origin/main'.
```
リモート追跡ブランチ`origin/main`をローカルブランチ`master`の上流ブランチとして設定した。
改めて`git merge`する。
```
> git merge
fatal: refusing to merge unrelated histories
```
適当に空コミットを作ったので、`--allow-unrelated-histories`をつけて回避する。
```
> git merge --allow-unrelated-histories
Merge made by the 'ort' strategy.
(省略)
```
マージできた。

続いて`git push`を試みる。
```
> git push
fatal: The upstream branch of your current branch does not match
the name of your current branch.  To push to the upstream branch
on the remote, use

    git push origin HEAD:main

To push to the branch of the same name on the remote, use

    git push origin HEAD
```
上流ブランチのブランチ名と現在いるブランチのブランチ名が一致しないと怒られた。
調べた結果、`git push`を引数なしで実行した時の振る舞いは`push.default`という設定値で決まり、デフォルト値だと、上流ブランチにプッシュするが、ブランチ名が異なる場合はプッシュを中止するらしい。
この場合は、ローカルのどのブランチをリモートのどのブランチにプッシュするか指定する必要があるみたい。
```
> git config --list
remote.origin.url=git@github.com:test/Repository.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/main

> git push origin master:main
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 413 bytes | 206.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:test/Repository.git
   3ce55dd..33e1d25  master -> main
```
ちゃんとプッシュできた。
次にブランチ名を一致させた場合、引数なしで`git push`できるかを確認する。

リモートブランチと同じ名前のローカルブランチ`main`を作成し、`switch`する。
```
> git branch main

> git branch
  main
* master
> git switch main
Switched to branch 'main'
```

ローカルブランチ`main`の上流ブランチとして、リモート追跡ブランチ`origin/main`を設定し、`git fetch`、`git merge`を実施する。
```
> git branch -u origin/main
branch 'main' set up to track 'origin/main'.

> git config --list
remote.origin.url=git@github.com:test/Repository.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/main
branch.main.remote=origin
branch.main.merge=refs/heads/main

> git fetch

> git merge
Already up to date.
```

適当にファイルを更新してコミットする。
```
> echo "test3" >> a.txt
> git add a.txt
> git commit -m "test3"
[main 73a359b] test3
 1 file changed, 0 insertions(+), 0 deletions(-)
```

`git push`する。
```
> git push
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 539 bytes | 269.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To github.com:test/Repository.git
   33e1d25..73a359b  main -> main
```
引数指定なしでプッシュできた。

改めて、新しいローカルリポジトリを作成し、`git push`についてもどんな設定値が必要か確認していく。

```
> mkdir test2
> cd test2
> git init

> git push
fatal: No configured push destination.
Either specify the URL from the command-line or configure a remote repository using

    git remote add <name> <url>

and then push using the remote name

    git push <name>
```

リモートを登録しろと怒られたので登録後に再度`push`を試みる。

```
> git remote add origin git@github.com:test/Repository.git
> git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin master
```
上流ブランチの設定も必要らしいので設定する。
```
> git branch -u origin/master
fatal: the requested upstream branch 'origin/master' does not exist
```
怒られた。
リモート追跡ブランチが作成されていないため、`git branch -u`では設定できなさそう。
`git push`時に`--set-upstream`で指定する。
```
> git push --set-upstream origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 233 bytes | 116.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:test/Repository.git
 * [new branch]      master -> master
branch 'master' set up to track 'origin/master'.
```
リモート追跡ブランチ`origin/master`が作成され、ローカルブランチ`master`の上流ブランチに設定された。
また、リモートブランチ`master`が作成され、プッシュされた。
2回目以降は引数なしでpushできた。

## まとめ
- `git fetch`のリモート名のデフォルトは`origin`
- `git fetch`を引数なしで実行する場合は、`origin`という名前でリモートリポジトリの登録が必要
- `git fetch`の対象は`remote.origin.fetch`で決定される。
- `git merge`のデフォルトのマージ対象は上流ブランチ
- `git merge`を引数なしで実行する場合は上流ブランチの設定が必要
- `git push`を引数なしで実行する場合は、`origin`という名前でリモートリポジトリの登録と上流ブランチの設定が必要
- リモート追跡ブランチが作成されていない場合は、`git push`時に`--set-upstream`でプッシュと同時に作成できる
- `git push`を引数なしで実行する場合、ローカルブランチと上流ブランチの名称を一致させる必要がある

冒頭の記事で疑問点として挙げていた上流ブランチについては、通常はリモート追跡ブランチを指すと考えてよさそう。

## 参考
https://tracpath.com/docs/git-fetch/

https://tracpath.com/docs/git-merge/

https://tracpath.com/docs/git-push/

https://www-creators.com/archives/1472