Git/GitHub

https://git-scm.com/

https://github.co.jp/

基本操作

これから使い始める人向けスライド:

新しいリポジトリの作成

  1. GitHub のサイト右上の “+” ボタンから “New repository” を選択し、“Create repository” する。

  2. 手元の PC にローカルリポジトリをつくる:

    mkdir new_repository
    cd new_repository
    git init
  3. ファイルを add して commit してもいいし、空の commit をしてもいい:

    ## ファイルをつくってadd&commit
    echo "Hello, Github" > README.md
    git add README.md
    
    ## コミットメッセージを添える
    git commit -m "Initial commit"
    
    ## 空のコミットでもいい
    git commit --allow-empty -m ":coffee: Create repository"
  4. リモートリポジトリを紐づけて push:

    git remote -v        # 何も表示されない
    
    ## HTTP の場合
    git remote add origin https://github.com/*username*/*new_repository*.git
    ## SSH の場合
    git remote add origin git@github.com:*username*/*new_repository*.git
    
    git remote -v        # リモートリポジトリが表示されることを確認
    git branch -M main
    git push -u origin main

    Private リポジトリの場合、 SSH で紐付けしないと下り (fetch, pull) のときもパスワードを要求される。

手元の変更をリモートリポジトリに反映

基本: git addgit commitgit push

  1. 手元でファイルをいじって変更を確認:

    echo "Hello, Github" > README.md
    git status   # README.md が Changes not staged for commit: に表示される。
  2. 変更したファイルをインデックスに登録:

    git add README.md
    git status     # README.md が Changes to be committed: に表示される。
  3. 変更をコミット:

    git commit -m "modified hoge.txt"
    git status   # nothing to commit, working tree clean となる。
    git log      # コミットが表示される。
  4. リモートリポジトリへ push:

    git push

リモートリポジトリの変更を手元に反映

基本: git fetchgit merge もしくは git pull

  • リモートブランチの状態を手元のファイルまで一気に反映:

    git pull
  • リモートブランチの変更を一度ローカルのアップストリームブランチに反映させてから手元のファイルに反映:

    git fetch
    git log --all
    git merge

.gitignore

https://docs.github.com/ja/get-started/getting-started-with-git/ignoring-files

リポジトリのルートディレクトリに .gitignore を配置して、 Git の管理から除外するファイルを制御する:

## 場所を問わず特定のファイル・ディレクトリを除外
hoge

## .gitignore が置かれたリポジトリの特定のファイル・ディレクトリを除外
/hoge

## 場所を問わず特定のディレクトリの除外
dir/

## .gitignore が置かれたリポジトリの特定のディレクトリを除外
/dir/

## 特定のファイル・ディレクトリのみ追跡
*
!hoge

## ワイルドカードによる指定
/*.py
/*.Rproj

~/.config/git/ignore でグローバルに除外対象を設定:

.DS_Store

すでに追跡しているファイルを除外するにはトラッキングを外す:

git rm --cached <FILE_NAME>

SSH 接続

https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/about-ssh

手順:

ssh -T の際に permission denied となる場合

https://docs.github.com/ja/authentication/troubleshooting-ssh/using-ssh-over-the-https-port

ssh-keygen の際にファイル名を変更していると認証がうまくいかない。 ~/.ssh/config に以下を追記して解決。

~/.ssh/config
Host github github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa_git    # Github 用の秘密鍵

git submodule

外部のリポジトリを自分のリポジトリのサブディレクトリとして取り込む仕組み。

git submodule add https://github.com/<username>/<repository>.git <directory>

submodule を最新版に更新する

git submodule foreach git pull
git add <submodule>
git commit -m "updated submodule"
# git push

サブモジュールを含むリポジトリを clone するとき

普通に clone してくるとサブモジュールの中身は空になっている。 clone する際に、

git clone --recurse-sebmodules <repository>

としてサブモジュールの中身ごと落としてくるか、親リポジトリをクローンしたあと、

git submodule update --init

してサブモジュールの中身を取得する。

そのほかのコマンド

  • 直前の操作を修正:

    ## 直前のミスコミットを修正
    git commit --amend -m "hogehoge"
    
    ## commitの取り消し
    git reset --soft HEAD^
    
    ## addの取り消し
    git restore --staged file_name
  • すでにリポジトリに登録されたファイルを削除:

    git rm --cached *file*
  • ファイル名を変更:

    git mv file file_renamed
  • git stash

    git mergegit pull の際、コミットするほどでもない手元の変更を一時的に退避するために使う。

    working directory と staging area の変更を退避する:

    git stash -u        # -u: Untrackedなファイルも含める

    退避した変更を確認:

    git stash list
    # stash@{0}: WIP on main: d426bc4 Fix a bug

    git mergegit pull でリモートの変更を手元に反映した後、 退避していた変更を戻す:

    git stash apply stash@{0} --index

    --index オプションなしだと、もともとステージングされていた変更も add 前の扱いで戻ってくる。

    退避していた変更を消す:

    git stash drop stash@{0}    # 退避内容を指定して削除
    git stash pop stash@{0}     # 退避内容を指定してブランチに戻すとともに削除
    git stash clear                     # 退避内容を全て削除
  • リポジトリ名を変更:

    • リモート側の操作: リポジトリのページ > “Setting” > “Rename” から変更

    • 手元の操作:ローカルリポジトリの名前と .git/config を書き換える

      mv repository_name_before repository_name_after
      sed -i -e 's/repository_name_before/repository_name_after/g' .git/config