[Git]作業ツリーが存在するときにリモートリポジトリーのコードを取得してみた
モチベーション
リモートリポジトリーのコードをベースに新しくプロジェクトを作成するときは git clone <リモートリポジトリのURL>
を実行すると簡単にリモートリポジトリーのコードを取得できます。ただ、既にプロジェクト(作業ツリー)がローカルに存在しており、リモートリポジトリーの一部/全てのコードを取得したい場合はこれではうまくいきません。この場合にどうしたかをメモします。
環境
- OS: Windows 11
- PowerShell: 5.1
- Git: 2.29.2
- VS Code: 1.80.1
想定ユースケース
- ローカルを正として扱う(差分をリモートリポジトリーから取得する)ユースケースを想定
- 以下のリモートリポジトリーから一部/全てのコードを取得する
事前準備
プロジェクト作成
リモートリポジトリーと同じReactのプロジェクトの方がわかりやすいと考えReactのプロジェクトを作成。
npx create-react-app working_tree_based -- template typescript
Gitでコードを管理する
cd working_tree_based
git init
ステージを確認してみる
git status
この時点ではまだステージングされていないので以下のメッセージが表示される。
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
README.md
package-lock.json
package.json
public/
src/
nothing added to commit but untracked files present (use "git add" to track)
ステージング
git add .
git status
ステージングされコミットの準備が整った。
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: .gitignore
new file: README.md
new file: package-lock.json
new file: package.json
new file: public/favicon.ico
new file: public/index.html
new file: public/logo192.png
new file: public/logo512.png
new file: public/manifest.json
new file: public/robots.txt
new file: src/App.css
new file: src/App.js
new file: src/App.test.js
new file: src/index.css
new file: src/index.js
new file: src/logo.svg
new file: src/reportWebVitals.js
new file: src/setupTests.js
コミット
一旦コミット。
git commit -m "first commit"
リモートリポジトリーから一部コードを取得
ここまでで一旦準備は整ったので、リモートリポジトリーからコードを取得してみる。
リモートリポジトリーの登録
git remote add origin https://github.com/shoji9x9/git_training
ローカル/リモートの差分確認
試しにローカル/リモート双方に存在するREADME.mdの差分を確認してみる。
git diff master origin/master -- README.md
リモートリポジトリーから一部コードを取得
リモートリポジトリーにだけ存在する(ローカルには存在しない).eslintrc.jsを取得してみる。
git checkout origin/master -- .eslintrc.js
ステージを確認してみる
git status
この時点ではまだ.eslintrc.jsはステージングされていないので以下のメッセージが表示される。
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .eslintrc.js
ステージング、コミット
後の作業に備え一旦コミット。
git add .eslintrc.js
git commit -m ".eslintrc.js追加"
リモートリポジトリーから一部コード(ディレクトリ)を取得
リモートリポジトリーにだけ存在する(ローカルには存在しない)src/utils/以下の全ファイルを取得してみる(以降のステージの確認、ステージングはここでは割愛)。
git checkout origin/master -- src/utils/*
リモートリポジトリーから一部コードを取得(上書き)
ローカルに存在するREADME.mdをリモートのREADME.mdで上書きしてみる。
git checkout origin/master -- README.md
上書き前に戻す
README.mdは元々ステージされた状態だったため、上記コマンドにより作業ツリー、ステージともにリモートリポジトリーのREADME.mdで上書きされている。これを元に戻すには以下のコマンドを発行する。
git restore -S -W README.md
試してはいないが git reset --hard -- README.md
でも同じことを実現できるはず。
【未実現】リモートリポジトリーから一部コードを取得(マージ)
ローカルのREADME.mdとリモートのREADME.mdをマージする。
-
git checkout --patch origin/master README.md
を実行したかったが、Perlが必要なため断念 -
git merge-file
を試してみたものの使い方が難しく断念。以下参考にしたサイト
リモートリポジトリーから全てのコードを取得
pullの設定
設定をせずに git pull
すると警告が出るため以下のコマンドを実行。意味合いは
Git 2.27 での git pull 時の warning について 参照。
git config pull.rebase false
pull
git pull origin master
このコマンドを実行すると以下のエラーが発生する。無関係な歴史を持つブランチをマージしようとしたときに発生するエラーの模様。
From https://github.com/shoji9x9/git_training
* branch master -> FETCH_HEAD
fatal: refusing to merge unrelated histories
これを回避するため --allow-unrelated-histories
オプションを付けたコマンドを発行する。
git pull --allow-unrelated-histories origin master
するといくつかのファイルで競合が発生。
From https://github.com/shoji9x9/git_training
* branch master -> FETCH_HEAD
CONFLICT (add/add): Merge conflict in package.json
Auto-merging package.json
CONFLICT (add/add): Merge conflict in package-lock.json
Auto-merging package-lock.json
CONFLICT (add/add): Merge conflict in README.md
Auto-merging README.md
Automatic merge failed; fix conflicts and then commit the result.
競合の解消
VS Codeの機能を利用し1つずつ競合を解消。
- Accept Current Change: ローカルリポジトリーを正とする
- Accept Incoming Change: リモートリポジトリーを正とする
- Accept Both Changes: 双方を残す
特定のファイルをステージから削除
git rm --cached package-lock.json
pull以前に削除すると、pullを実行したタイミングで以下のエラーが発生する(リモートリポジトリーにも該当のファイルが存在する場合)。
From https://github.com/shoji9x9/git_training
* branch master -> FETCH_HEAD
error: The following untracked working tree files would be overwritten by merge:
package-lock.json
Please move or remove them before you merge.
Aborting
ローカルリポジトリーの内容をリモートリポジトリーに反映
push
git push origin master
これで直前にステージから削除したpackage-lock.jsonはリモートリポジトリーにも表示されなくなる。ただし、過去のコミットを見ればpackage-lock.jsonの内容も確認可能なため、万が一機密性の高いファイルをアップロードしてしまった場合は Gitからファイルを完全に削除する方法(BFG Repo-Creaner) など参考に対応する。
Discussion