git 備忘録


## 私のgitの基本的なワークフロー

いつも私がやっているgitのワークフローです。


### 1. git init or git clone

まず、フォルダ（ディレクトリ）をgitで管理するためには、最初にgit init かgit cloneをする必要があります。

二つの違いはこんな感じ。


git cloneを使うとき : インターネット上のディレクトリ"（リモートリポジトリ）を自分のPCでgitを使って管理するとき
git initを使うとき :　自分のPCにあるディレクトリ（ローカルリポジトリ）をgit で管理するとき

実際に打つコマンドは下記の通り。

### git clone
```
git clone <ここをgithubからコピーできるurlに置き換えます>
```
### git init
```
git init <ここをgitリポジトリで管理したいディレクトリの場所を置き換えます。(例：git init ~/projectA)>
```
### 2. git branch(「ブランチは作らないよ」って人はスキップして3に進む)

gitにはブランチというものがあります。

少し難しいのですが、だんだんと慣れていきましょう。




### git branch ,git checkout

まず、ブランチを作ってから、その新しく作ったブランチにgit checkout で移動します。
```
git branch <ここを新しく作るブランチの名前に置き換える>
```
```
git checkout <ここをさっき作った新しいブランチの名前に置き換える。>
```
### 3.コードを書く。

ここはコードを書くだけです。

あんまgitに関係はありません。

つまりあんま書くことないです。

### 4. git add <ディレクトリ名 or ファイル名>

このコマンドで、gitにどの変更を管理するか教えます。

注意：初めてgit addする前に、.gitignoreを使おう。

.gitignoreで、管理したくないファイル、ディレクトリを指定して、gitの管理から外しましょう。

外さないと、やたらと重いファイルや、インストールしたライブラリ、個人情報を含むファイルまでgit pushしてしまいます。

例えば、node_modules/というディレクトリをgit で管理したくない時、こうやって.gitignoreを書きます。
```
# ディレクトリを指定する場合
node_modules/
```
例）すべての変更をgitで管理したいとき。

git init ,git cloneで指定したディレクトリの一番上に移動して、以下のコマンドを打つ。
```
git add . 
```
例）一部の変更をgitで管理したいとき。

変更したファイル(abc.py)、そのファイルを含むディレクトリ(~/projectA/xyz/)をgitで管理したいときは、
```
git add abc.py ~/projectA/xyz/
```
### 5. git commit 

commitとは、先ほどgit addで指定したディレクトリ、ファイルの変更を記録（ゲームで言うセーブ）することです。

gitで変更をcommitすれば、commitした時点でのコードに巻き戻すことができます。
```
git commit -m "ここにどんな変更をしたのか、簡単な説明を書く。"
```
### 6. git push

pushとは、インターネット上にあるディレクトリ（リモートリポジトリ）に、自分のPCでの変更を記録することです。

git push <リモートリポジトリのurl or リモートリポジトリの名前>　<リモートブランチの名前>

## gitコマンド紹介ミスった時の対処法、必要だったコマンド

上のワークフローでミスったときに打つgitコマンドをまとめました。

### git branchの名前を変更する
```
git branch -m <変更したいブランチ名> <変更後のブランチ名>
```
### 新しくgit ブランチを作って、リモートブランチをそこにpullする
```
git checkout -b <新しいローカルブランチ> <既存のリモートブランチ>
```
### 誤ったbranchで作業して、コードを書いてしまった場合、変更を全て違うブランチに移動させる。

まずは誤って作業してしまったブランチの上に行ってこのコマンドを打ちます。
```
git stash 
```
これで、変更をstash(退避)することができました。

次は、変更を反映したいブランチに移動した後、このコマンドを打ちましょう。
```
git stash apply # もっとも最近のstashされた変更が今のブランチに反映される。
```
これで、完了です。git diffなどを打って確かめてみましょう。

### stashを削除
```
//stashの一覧を確認
$ git stash list
//stashを削除。
$ git stash drop <stash名>
```
<stash名>を省略すると、最新のstashを削除します。

### git addをする前に戻す。

ステージングしたファイルをステージングしていない状態にします。

編集は取り消されません。
```
git restore --staged <file> ...
```
これ、add した直後に git status すると、「このコマンド(git restore --staged …)を使えばunstageできるよと教えてくれます。」(use "git restore --staged …" to unstage)

### git add の取り消し。　

これは、取り消しです。取り戻しじゃないです。編集して、addして、このコマンドを使えば、綺麗さっぱりその編集は消えます。
```
git rm --cached -r .
```
### addしてないファイルを最新コミット（HEAD）の状態に戻す
```
git checkout HEAD <FILE_NAME>
```
## gitignoreがうまく反映されない時

### どのファイルがignore(無視)されているのか確認しよう。
```
# gitでignoreされているファイルが表示されるコマンド
$ git status --ignored
# gitで管理されているファイルが表示されるコマンド
$ git ls-files
```
ここで確認してみましょう。

このコマンドはgit addする前に使ってもうまくいかないという過去の記事を見たことがあるのですが、今ではgit addする前でも使うことができます。

### typo（打ち間違い）してないか確認しよう。

地味ですが、私はこのミスが一番多かったので気をつけましょう。

### 一度commitしたファイルをgit管理から外したい場合

一度commitしたファイルをgit管理から外したい(ignoreしたい)場合

.gitignoreに管理から外したいファイルを書く。

このコマンドを実行する。
```
git rm -r --cached <管理から外したいファイル>
```
### !は一度除外した（ignoreした）ファイルを元に戻すための記号。

私の理解では、

ファイルAをgit管理下におきたい。それ以外はgit管理下に置きたくない。

という場合、.gitignoreの中では、一度ファイルAを除外して、ファイルAを管理下に置くという、周りくどいやり方をしなければいけません。

つまり、こんな感じ。

#.txtファイルのみgitで管理したい時。
*
!*.txt

## 間違えてgit pushしたとき、リモートリポジトリのファイル、ディレクトリを消す。

よく、 __pycache__や、node_modules をgithubにpushしてしまう方へ

手順は6つです。

### 1. git log でコミットＩＤを確認

戻りたいコミットのIDを、確認しましょう。
```
$ git log --oneline
cccaac (HEAD -> master, origin/master) second commit
000fff initial commit        
```
#ここまで戻りたかったら、 000fffを覚えておきましょう。

### 2. git resetで追加する前のコミットに戻る。

#1ステップ目での000fffをcommmit IDにすれば、そのコミットまで戻れます。
```
$ git reset <commit ID> --soft 
```

取り消したコミット分の編集はaddされている状態になります。

ここで普通にコミットすれば、git reset <commit ID> --softする前に戻るようなものです。 

### 3. gitignoreに管理から外したいファイルを書く。

.gitignore に書きましょう。

### 4. git resetで追加する前のコミットに戻る。

削除するのがディレクトリの場合、 -rが必要です。
```
$ git rm [-r] --cached <削除したいディレクトリ、ファイル>
```
### 5. git add, git commit

ここで、普通に、addして、コミットしましょう。
```
$ git add <--all または、gitで管理したいディレクトリ>
$ git commit -m "コミット時のコメント"
```
### 6. git push 

originは、リポジトリ名の例、masterはブランチ名の例です。書き換えてください。
```
$ git push -f origin master
```

## ローカルのmasterを、強制的にリモートのmasterに合わせる
### 1.リモートの情報をfetch
```
$ git fetch origin master
```
### 2. ローカルのmasterを、リモートのmasterに強制的に合わせる
```
$ git reset --hard origin/master
```