20190711のGitに関する記事は7件です。

[Git] ファイル単位でstashする

 
〜ローカルリポジトリで作業中〜

 
ワイ 「よ〜し作業終わったしcommitするゾ!」

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   fuga.py
    modified:   hoge.py

no changes added to commit (use "git add" and/or "git commit -a")

 

ワイ 「branch切り替えるのを忘れてmasterを変更してもうた・・・」

ワイ 「featureブランチに変更を移したい。。。」

git stash

そんな時に使えるのがgit stash
ファイルを一時的に退避させることができる。
もちろんbranch間の移動も可能なので無理やり汚いcommitをする必要もない。

$ git stash
Saved working directory and index state WIP on master: e1c4afb [feat] hoge.py fuga.py

$ git status
On branch master
nothing to commit, working tree clean

$ git stash list
stash@{0}: WIP on master: e1c4afb [feat] hoge.py fuga.py

こんな感じで変更が退避されて$ git stash listで確認することができる
他のbranchに適用させたい時は以下のようにする

$ git checkout feature/hogefuga
Switched to branch 'feature/hogefuga'

$ git status
On branch feature/hogefuga
nothing to commit, working tree clean

$ git stash pop
On branch feature/hogefuga
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   fuga.py
    modified:   hoge.py

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (0706e9eb4284f2fcd1bb6ac6a049beb0e52ffdb6)

おけまる!

ファイル単位でstashしたい

特定のファイルだけ別のbranchに移動させたいという場合もあるだろう。
$ git stashだけだと変更の及んだ全てのファイルがstashされてしまう。
ファイル単位でstashするには以下のようにする。

// 退避する時
$ git stash push -- <filepath>

// 戻す時(番号はstash番号)
$ git stash pop stash@{0}

実際にやってみたのが以下

$ git branch
  develop
  feature/hogefuga           // ここにfuga.pyを移動
  feature/hogehogefugafuga   
* master                     // hoge.py fuga.py
$ git stash push -- hoge.py
Saved working directory and index state WIP on master: e1c4afb [feat] hoge.py fuga.py

$ git stash push -- fuga.py
Saved working directory and index state WIP on master: e1c4afb [feat] hoge.py fuga.py

$ git stash list
stash@{0}: WIP on master: e1c4afb [feat] hoge.py fuga.py
stash@{1}: WIP on master: e1c4afb [feat] hoge.py fuga.py

$ git checkout feature/hogefuga
Switched to branch 'feature/hogefuga'

$ git stash pop stash@{0} # fuga.py
On branch feature/hogefuga
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   fuga.py

no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{0} (3c71ae19147fc1ef56a748df9fe849471f933956)

できた!

終わりに

stash自体まだまだ便利なオプションとかあるのでそこは各自で調べてもらえると嬉しいです。
快適なgitライフを送りましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gitコマンド

書いてあること

  • よく使うGitコマンドの利用方法
  • Git初期設定

環境

  • CentOS Linux release 7.6.1810 (Core)
  • Git 2.22.0

事前準備

CentOSへGitをインストール

初期設定

設定ファイル(.gitconfig)は各ユーザーのホームディレクトリに作成される

設定確認

bash
$ git config --list

よく使う設定

bash
#ユーザー名、メールアドレスを登録
$ git config --global user.name
$ git config --global user.email

#カラー設定
$ git config --global color.ui auto
$ git config --global color.diff auto
$ git config --global color.status auto
$ git config --global color.branch auto

#Push方式
$ git config --global push.default simple

#ファイル名の大文字・小文字を区別
$ git config --global core.ignorecase false

#UTF8問題対策
$ git config --global core.precomposeunicode true

#日本語ファイルの文字化け防止
$ git config --global core.quotepath false

#エディタをvimに設定
$ git config --global core.editor 'vim -c "set fenc=utf=8"'

Gitコマンド

共通・準備

ローカルリポジトリ初期化

bash
$ git init

ローカルリポジトリ状況確認

bash
$ git status

変更履歴を確認

bash
#デフォルト
$ git log

#ログを1行で表示
$ git log --oneline

#ログをグラフ表示
$ git log --graph

コミット

インデックスにファイルを追加

bash
#ファイル指定
$ git add <ファイル名>

#ディレクトリ指定
$ git add <ディレクトリ>

コミット

bash
$ git commit -m "コメント"

プッシュ

リモートリポジトリの確認

bash
$ git remote -v

リモートリポジトリを登録

bash
$ git remote add <name> <URL>
$ git remote add origin https://・・・

リモートリポジトリのURLを変更

bash
$ git remote set-url <name> <URL>

リモートリポジトリ名を変更

bash
$ git remote rename <old-name> <new-name>

リモートリポジトリを削除

bash
$ git remote rm <name>

プッシュ

bash
$ git push -u <アドレス> <ブランチ>
$ git push -u origin master

クローン

クローン

bash
$ git clone <URL> <ディレクトリ名>

プッシュ

bash
#クローンしたリポジトリではアドレス、ブランチを省略可能
$ git push

プル

プル

bash
$ git pull <アドレス> <ブランチ>
$ git pull origin master

ブランチ

一覧を確認

bash
$ git branch

ブランチを追加

bash
$ git branch <ブランチ>

チェックアウト(切り替え)

bash
$ git checkout <ブランチ>

ブランチのマージ

bash
#masterとマージ
$ git checkout master
$ git merge <ブランチ>

ブランチを削除

bash
$ git branch -d <ブランチ>

タグ

タグの確認

bash
$ git tag

タグの確認(コメント付き)

bash
$ git tag -n

軽量タグを追加

bash
$ git tag <タグ>

コメント付きタグを追加

bash
$ git tag -am "コメント" <タグ>

タグを削除

bash
$ git tag -d <タグ>

参考

Gitをインストールしたら真っ先にやっておくべき初期設定
最低限しておくといいgitconfigの設定
gitで便利なエイリアス達
サルでもわかるGit入門

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

チームにVSCode利用者が多い場合は、Gitリポジトリにsettings.jsonをコミットしよう

概要

チームでVSCodeを使うエンジニアが多い場合には、VSCodeの設定ファイルをリポジトリに乗せることが得策であるお話です。

チーム開発で起こる問題

フォーマットのばらつき

チーム内のエンジニアはもちろん別々の人間なので、書くコードは人それぞれです。
ある程度ルールを統一したからと言っても、どこかで必ず差異が生じてきます。
これらは、コードレビュー時に目視で確認することもありますが、細かすぎる作業なので極力避けたいものです。

具体例

  • イコールの位置揃え
  • 文字列を''で囲むか、""で囲むか。
  • メソッド定義の中括弧は改行してから書くかどうか

規約の不認識

こちらもある程度ルールを決めていても、必ずばらつきが出てきます。
物によっては、レビュー者も規約内で不認識の部分があり、規約に沿っていないコードがマージされてしまうことが多かったりします。
レビューでは気づきますが、ビジネスロジックのコアな部分ではないので、できればあまり時間を割きたくない部分です。

具体例

  • 1行は何文字までOKか
  • プロパティのアクセス修飾子どうするか
  • メソッド名はキャメルケースかスネークケースか

ルールを決めるだけではまだ足りない

ここで、これらをプロジェクト内でルールとして決めたりすることが多かったりします。
しかし、ここでルールを決めただけだと、下記の問題が生じたりします。

  • コード規約やフォーマットの種類をキャッチアップする時間が必要
  • 運用していても、意識し続けない限り、どこかで崩れる
  • これらをチェックするレビューの時間が勿体無い

解決策

そんな時には、エディターにお任せしてしまいましょう。
特に、VSCodeの場合は、エディター内での設定ファイルを共有することができるので、それを活用すると楽です。

どんなことをしてくれるのか

上記の問題を解決できます。

  • 自動でフォーマットを整えてくれる

    • ""がある場合は''に変える
    • 1行が長すぎた場合は、自動で改行
    • インデントを自動で揃える
  • コード規約に反していた場合の注意

    • 非推奨の関数を使っている場合など

どうやれば良いのか

チームで共有するリポジトリ内に、.vscode/settings.json を作りましょう。
例えば、Vue.jsなどJavaScriptを中心としたプロジェクトの場合は、下記のような設定があります。

settings.json
{
  "editor.formatOnSave": false,
  "eslint.autoFixOnSave": true,

  // Vus.js用のフォーマット設定
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    {
      "language": "vue",
      "autoFix": true
    }
  ],

  "prettier.eslintIntegration": true,
}

eslintに従って、ファイル保存時にフォーマットを自動で整えてくれる設定です。
prettierというプラグインを使う前提なので、prettierをVSCodeにインストールしておけば、プロジェクトをcloneした人は何もせずとも、上記に従って自動フォーマットが行われる環境になります。

そのため、コードレビュー時にフォーマットを気にする必要はありませんし、開発者もフォーマッタや規約に関してキャッチアップする必要はありません。
時間も大幅短縮で幸せになれますね。

最後に

エディターは人それぞれ異なるため、複数のエディターに対する設定をプロジェクトのリポジトリに入れておいても良いでしょう。
自動化できるところは自動化し、ビジネスロジックに集中することで、より品質が保たれる上に開発のスピードが早くなるかと思います。
ぜひ参考にしてみてください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azure DevOps Repos(リポ)の超概要&Gitについて簡単に説明

ーーGitを理解されている方は読む必要がありません。

Azure DevOps全体の概要については、こちらをご覧ください。
https://qiita.com/mstakaha1113/items/1cf45a5119e1397d0315

"Repos(リポ)"は、生産物を保存するサービスです。
サービスとして何があるのかご紹介します。
超概要なので、具体的な画面の説明はありません。

そもそもリポジトリ?

"Repos"は、ソースコードを中心とした生産物を履歴などを意識しながら保管できるサービスです。
このような仕組みを一般的に"リポジトリ"と呼びます。
過去、様々なリポジトリが存在していました(もちろん今も存在しています)。
たとえば、

  • VSS
  • CVS
  • Subversion

など、聞いたことや使ったことがあるのではないかと思います。
もしリポジトリを使っていない場合、開発を進めるたびに新たなフォルダを作ってコピーして改修するというような作業に明け暮れることとなります。
これ自体も問題なのですが、複数名で複数の課題に立ち向かっていく際、誰がいつどこをどのように修正したのか、それをどうレビューし承認し結合するのかということを制御するのが非常に困難になります。
このような課題を解決すべく、リポジトリはあります。

リポジトリは、みんなが実施した作業を無駄なくバリューに変換するためのものです。

"Repos"は2種類のリポジトリを提供している

"Repos"では、TFVCベースとGitベースという2種類のリポジトリを提供しており、プロジェクトごとにどちらを採用するかを選択することができます。
端的に書くと、

  • TFVC:中央集権的なリポジトリ、中央に1つリポジトリを配置して、全員がそこに対して生産物を登録していく。
  • Git:地方分権的なリポジトリ、ある程度自由に中央のリポジトリをコピーしてきて、そこに対して生産物を登録、その後任意のタイミングで中央に申請して取り込んでもらう。

というような差がありますが、世の流れもありますし差を追求するのはやめましょう。

これからやるならGitベース1択

もちろん個人の主観ではありますが、これからAzure DevOpsを使うのであればGitを採用してください。
この先の説明も、Gitのみを対象としています。

"Repos"のメニュー

20190708-1.png

かなりザックリした説明になります。
そもそものGitに関する簡単な説明は、このあと書きたいと思います。

Files : ブランチに登録されているファイル一覧を表示します。
Commits : ブランチへのコミットの変遷を表示します。
Pushes : ブランチに対してプッシュされた情報を表示します。
Branches : ブランチの一覧を表示します。
Tags : タグ付け機能がありますので、それを利用します。
Pull requests : "ブランチで作ったものを承認して取り込んでほしい"という要求を出したり承認したりします。

Gitの簡単な説明

冒頭で"Gitは地方分権的なリポジトリ"と書きました。ここでは、Gitと、中央集権的なリポジトリに触れて、メニューの理解を進めたいと思います。
簡単に書きすぎているが故の説明不足など、ご容赦ねがいます。

中央集権的なリポジトリはファイルをコピペする

まずはGitとは異なるポリシーを持ったリポジトリをおさらいします。
たとえばVSSのようなリポジトリを使った開発を行う場合、リポジトリからフォルダやファイル構成を自分のPCにダウンロードしてきます。
20190708-2.png
取得するのは、主に最新のフォルダやファイルの構成です。
ファイルを更新したのち、リポジトリにアップロードを行います。
20190708-3.png
アップロードするのは、フォルダ構成やファイルそのものです。
どんなつもりでアップロードしたのかをコメントとして記述しますが、このコメントや履歴は中央にある1つのリポジトリで一括生成、管理します。
とてもシンプルでわかりやすいのですが、いくつかの問題も発生します。(実際には各ソフトウェアで解決が行われており問題に直面することは少ないと思いますが、理論上は以下のとおりです。)

  • 複数名で同じファイルを改修したい場合、ファイルの取り合いが発生する
  • 複数の案件に対する改修を実施している場合、コミットタイミングがわからなくなる
  • 上記2点を踏まえると、状況次第では改修の"待ち"が発生する

Gitはリポジトリそのものをコピペする

Gitでは、リポジトリそのものを自分のPCにクローン(ダウンロード)します。
20190708-4.png
作業は個人のPCの中にクローンされたリポジトリに対して実施します。
基本的には1案件に対する複数ファイルの改修を行い、ローカルのリポジトリに対してコミット(改修後のファイルの登録)を行います。
全ての改修が終わり、テストも完了した時点で、このローカルのリポジトリを元あった場所(たとえばAzure DevOpsのRepos)にプッシュ(アップロード)します。
リポジトリとしてクローンしてくることのメリットは、コミット時に顕著になります。
20190708-5.png
リポジトリには、最終的なファイルだけではなく、ローカルリポジトリを更新した履歴が入っています。ファイルと履歴を一式送り込むことができますので、受け入れる側は、改修の意図を理解しながら受け入れるか否かを判断できます。

実際にはどう扱うのか

先ほどの絵ではリポジトリは1つの大きな枠として表現しましたが、実際には1つではありません。
実際にはこのように扱います。
20190708-6.png
時間の流れを意識しながら、図の左側から右側へ向けて説明します。
はじめ、リポジトリは"master"という場所から始まります。
基本的な作業は

  • "master"から"branch"(改修用のコピー品)を作る
  • "branch"をローカルに"clone"(ダウンロード)する
  • 改修しテスト、適宜"clone"したリポジトリに"commit"(登録)する
  • "clone"したリポジトリを"push"(アップロード)する
  • "Pull request"を発行しレビューと"merge"(ファイルと改修履歴の統合)を依頼する
  • "branch"を"master"にマージする

という工程で行われます。
案件Aは、この基本的な作業です。緑色がmaster branch、青色のブランチを作成してオレンジ色のcloneを実施、改修内容をpush(オレンジ)して、ブランチ(青)をmaster(緑)にマージしています。
案件Cは案件Bのマージ前に作業を開始しています。案件Cのマージ時には案件Bに伴う改修が入ったmasterと比較して、案件Cの変更をマージするか否か選択します。同じファイルを改修している際は"conflict(衝突)"をGit側で検知してくれますので、状態を確認し、案件Cの取り込み方を検討します。
案件Dと案件Eも同じ構図です。こちらは後から始まる案件Eを先にマージしていますが、すべての状態を履歴として管理していますので、問題があっても確認は容易です。
これらの状態の確認や承認を実施するために"Pull request"が存在します。
他にも多くの機能がありますが、主題ではありませんので割愛します。

まとめ

"Repos"についてメニューを確認しました。
"Repos"はリポジトリのことです。リポジトリを使えば、ファイルとその改修履歴を扱うことができます。
Gitは分散型のリポジトリです。最初から分散することを意識していますので、ファイルの取り合いやまわりの作業者との協調から解放されます。
その変わり、マージするときは内容の差異を正しく評価しなければなりません。Gitはそのことも容易に扱える仕組みになっています。
動画のようなもので無い限り、できるだけ開発中の資産はリポジトリに登録するようにしましょう。
設計書のようなドキュメントであってもリポジトリの利用をおすすめします。(設計書は無い方が良いですが、全部はなくせないと思いますので。)
また、リポジトリに入れたものは差分を確認できますので、差分を確認できるテキストベースの情報を生産するようにしましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Gitのリベースでベースが変更される際に、コミット番号が変わる件を確認する

概要

Gitを用いていて、わりとわかりにくい「リベース」について。

developブランチと、ある時点のdevelopから派生したfeatureブランチ(feature/dev_#50としました)があったとします。
developがコミットされて先に進んでしまったときに、あたらしい時点のdevelopからの派生として、feature/dev_#50を リベースするシーンがあります。

image.png

こういうことですね。

コミット履歴は前のコミット番号を保持する というGitの性質において、リベースした後のコミットたち(おもに5d6a09d,ef3cd3bのことです)のコミット番号ってどうなるのかな?ってのを見てみます。

前準備

git init
echo "hello" >> Calc.java
echo "hello" >> Calc2.java
git add Calc.java && git add Calc2.java   && git commit -m 'initial'
git checkout -b develop && git checkout -b feature/dev_#50

いま時点の状態を確認します。

$ git log --oneline --graph
* 39eca7c (HEAD -> feature/dev_#50, master, develop) initial
$

develop(39eca7c) から feature/dev_#50 がブランチされました。SourceTreeでみるとこうです。
image.png

つづいて feature/dev_#50 に2回コミットしてみます。

git checkout feature/dev_#50
echo "hello from feature/dev_#50" >> Calc2.java
git commit -a -m '1. modified in dev_#50'

echo "hello from feature/dev_#50" >> Calc2.java
git commit -a -m '2. modified in dev_#50'

いま時点の状態を確認します。

$ git log --oneline --graph
* ef3cd3b (HEAD -> feature/dev_#50) 2. modified in dev_#50
* 5d6a09d 1. modified in dev_#50
* 39eca7c (master, develop) initial
$

develop(39eca7c) から派生した feature/dev_#50 はいま時点 ef3cd3b を指しています。

つづいて、develop に1つコミットします。

git checkout develop
echo "hello from develop" >> Calc.java
git commit -a -m 'modified in develop'

いま時点の状態を確認します。

$ git log --oneline --graph
* f618196 (HEAD -> develop) modified in develop
* 39eca7c (master) initial
$

39eca7c を指していたdevelopはいま、f618196を指しています。feature/dev_#50 との関係を見るためSourceTreeで見てみると、、、

image.png

  • develop は f618196
  • feature/dev_#50 は ef3cd3b

を指していることが図からもわかります。

リベースしてみる。

さてリベースについてです。
リ・ベースとはその名の通り、最初 39eca7cを指していた develop、から派生した feature/dev_#50 を、いまの f618196を指しているdevelop から派生するように切り替えるということです。 図示してみると(最初の図ですが)

image.png

こういうことです。とするとコミットログは、

4番目:ef3cd3b (feature/dev_#50 のコミット2個目)
3番目:5d6a09d (feature/dev_#50 のコミット1個目)
2番目:f618196 (いまのdevelopが指しているコミット)
1番目:39eca7c

となるイメージですが、3,4番目の 5d6a09d,ef3cd3bは、いまのdevelop(f618196) からブランチした後の新たなコミットとなり、新規にコミット番号が振られることになります。

やってみると、、、

git checkout feature/dev_#50
git rebase develop

さあ、いま時点の状態を確認します。

$  git log --oneline --graph
* d227747 (HEAD -> feature/dev_#50) 2. modified in dev_#50
* 503a3d3 1. modified in dev_#50
* f618196 (develop) modified in develop
* 39eca7c (master) initial
$

image.png

想定通りとなりました。

リベースは派生元を切り替えるわけなので、派生先のコミット達は軒並み、新規コミットとしてあつかわれることがわかりましたね。。

おつかれさまでした。

関連リンク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Git管理をしたくないファイルをpushしてしまった

Git管理下に残したくないファイルをcommit pushしてしまった。

しかも、その後コミットを複数回重ねてしまい、revertやresetをしてファイル修正するのはめんどくさい
※それほど、重要なファイルコミットしたわけでもないことが大前提。

そんなときに

.gitignore
対象ファイルやディレクトリの指定

push後にgitignoreを追記しても、git管理や履歴には残ってしまうので
キャッシュを削除する。

git rm -r --cached .
git commit -m "キャッシュを削除し、gitignoreを反映"
git push origin 指定のブランチ

参考
https://laraweb.net/environment/3072/
https://qiita.com/kamesennin/items/226e3839e457b342b89f
https://qiita.com/Potof_/items/c75eba9cfa72819506de

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitHubで誤って違うブランチにマージしてしまった時にWeb上だけで戻す方法

状況

  1. masterとブランチAは同じコミット上にいる
  2. ブランチAを親ブランチとしてブランチBを作った
  3. ブランチBでソースをゴニョゴニョいじってコミット&プッシュした
  4. GitHubのWebでブランチBをブランチAにマージしようとして、:boom:誤ってmasterにプルリク出してマージしてしまった:boom:
  5. 間違いに気が付かずにWeb(リモート)でブランチBを削除した
  6. 間違いに気が付かずにローカルでブランチBを削除した
  7. クライアントツールの樹形図を見ていて間違いに気がついた:biohazard:

Web上だけで戻す(revert)方法

1. リモートで削除してしまったマージ元のブランチを復活させる

  1. [Pull Request]タブを開いて[Filters]に入力されている「is:open」を削除してEnter
  2. a.gif
  3. マージ済みのプルリクが表示されるので、間違ったマージを選択して開く
  4. 削除してしまったマージ元のブランチの横にある[Restore branch]ボタンでブランチを復活させる
  5. a.gif

2. マージを戻す

  1. マージしたところの横にある[Revert]ボタンで「マージを戻す用のプルリク」を作る
  2. a.gif

  3. ここで revert-{誤ったプルリクの番号}-{マージ元のブランチ名} というフォーマットの「マージを戻す用のブランチ」が自動で作成される

  4. 「マージを戻す用のプルリク」をマージする

  5. 「マージを戻す用のブランチ」を削除する(とっておきたかったら削除しなくてもOK)

3. 今度は間違えないようにマージをやり直す

  1. [Code]タブの[branches]タブで復活させたマージ元のブランチの横にある[New pull request]ボタンでプルリク画面を表示する
  2. マージ先ブランチが間違っていないことをすごくよく確認してプルリクを出してマージする

ローカルで削除したブランチはWeb上では戻せない

戻せたらスゴスギと思う。
プッシュしないでうっかりローカルブランチを削除してしまったから復活させたい!というときは git reflogHEAD で復活させられそう(やっていないけど)
git add とかしてなくてまだGit管理下にいないファイルはもう無理かも
【Git】削除したブランチは復活できる!Git初心者から中級者になりたい方へ | ジーニアスブログ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む