2014年10月24日金曜日

Gitlabで大文字小文字のリポジトリを正しく取り込む方法

このエントリーをはてなブックマークに追加 はてなブックマーク - Gitlabで大文字小文字のリポジトリを正しく取り込む方法

既存リポジトリを取り込むとき、リポジトリ名に大文字小文字がある場合にGitlabは勝手にに大文字も小文字にしてしまう。

これは困ったと思っていたら、実は直す方法が書いてあった。

Allow camelCase / PascalCase repo names

Settings→Rename repositoryで好きな名称に変更出来る。(ただし、危険な変更ではある旨が書いてあるので念のため、実行前にはリポジトリのバックアップなどしておくと良いと思います。)

2014年10月23日木曜日

[Git]過去のリビジョンに戻る場合でのgit checkoutとgit reset --hardの違い

このエントリーをはてなブックマークに追加 はてなブックマーク - [Git]過去のリビジョンに戻る場合でのgit checkoutとgit reset --hardの違い

仕事で過去のリビジョンに戻る方法はどうすれば良いのか?という質問があったのだが、git checkoutとgit reset –hardを使う場合の違いについてよく分かってなかったので調べてみた。

指定リビジョンに戻す

既に記載の通り、2つやり方がある。

$git checkout <commit>

もしくは

$git reset --hard <commit>

である。

ただし、二つは大きな違いがある。

git checkout <commit>

指定されたコミットIDのリビジョンに作業ディレクトリ内のファイルが変更される。ブランチは detached HEAD状態となり、この状態ではコミットなどを行ってもリポジトリに保存されない。(厳密には少し違うが) つまり、read only状態で指定リビジョンの状態確認が出来る。

元のブランチに戻る場合、以下のように元々のブランチ名を指定すれば良い。

$git checkout master

基本的にread onlyであるが、別途ブランチを作成する事で、リポジトリへの追記も可能。

git reset --hard <commit>

現在のブランチのまま、指定されたリビジョンに作業ディレクトリ、ステージング環境、HEADが変わる。もし作業ディレクトリに編集中のファイルがあったという場合にもその情報は失われてしまうので、実行の際には注意が必要。

また、元々のHEADの状態に戻る場合、git reflogを使うかORGI_HEADを使う必要がある。

$git reset --hard ORIG_HEAD

もしくは

$git reflog
$git reset --hard <commit>

結論

大半の場合、checkoutによる操作で事足りそう。そして、checkoutの方が安全。

参考

The git checkout Command

The git reset Command

detached HEAD状態から元に戻すコマンド (git, checkout, fix a detached HEAD, .git/HEAD, refs/heads/master)

git reset についてもまとめてみる

2014年10月14日火曜日

[Git]ローカルのコミットは入れず、リモートリポジトリの更新内容をブランチに取り込む

このエントリーをはてなブックマークに追加 はてなブックマーク - [Git]ローカルのコミットは入れず、リモートリポジトリの更新内容をブランチに取り込む

状態

  • masterブランチ。ローカルで1回コミットを行った。その後、リモートリポジトリが他のメンバーによって更新された。
  • devブランチ。ローカルで1回コミットをする前の状態のmasterからブランチを作成している。

やりたいこと

masterブランチのリモートリポジトリで行われた変更のみをdevブランチに反映したい。 ただし、masterブランチでのローカルで行われたコミット内容はdevブランチに反映したくない。

結論

$git fetch
$git checkout dev
$git merge origin/master

fetchでorigin/masterリモートブランチを最新化し、devブランチにorigin/masterをmergeする。

本作業と同時にmasterブランチにリモートリブランチ(origin/master)のコミットを反映しても良い場合には以下でもOK。

$git pull
$git checkout dev
$git merge origin/master

git pullはgit fetchgit mergeを実行するので、上記だとmasterブランチも変更される。 単純にやりたいことだけやるのであれば、git fetchの方が合っていると思われる。

追記(11/23) トピックブランチにマスターの変更を反映することを2回以上行うと大量のコンフリクトが発生する。

gitで双方向にmergeしているとひどいはまり方をすることがある件

上記より、トピックブランチへマスターの変更を反映するのはマスターへマージする直前のみとし、それ以外の場合にはマスターからブランチを再作成し、cherry-pickなどを利用するのが良いと思われる。

これは駄目

$git pull
$git checkout dev
$git merge master

これを実行するとローカルのコミットもdevブランチに反映されてしまうのでNG。

大切な事

  • git pullとはgit fetchとgit mergeが行われている事を意識する
  • git fetchが実行されると作業ディレクトリの内容はは変更されず、リモートブランチ(orgin/masterなど)のみが変更される
  • masterブランチとリモートブランチ(origin/master)ブランチは別のブランチでである

参考にさせて頂きました

2014年10月7日火曜日

EclipseのプロジェクトをGradleでビルドし、JenkinsでもRobolectricを動くようにする

このエントリーをはてなブックマークに追加 はてなブックマーク - EclipseのプロジェクトをGradleでビルドし、JenkinsでもRobolectricを動くようにする

最近のAndroid開発環境はAndroidStudioがデファクトスタンダードっぽいのですが、関わっているプロジェクトがNDKを利用しており、まだAndroidStudioでは未対応なので、Eclipseを使っております。

そんなプロジェクトなのですが、Robolectricを使ってテストしており、Jenkinsで実行させる為にコマンドラインで実行するまでにした事をメモしておきます。

どうやったか

Antでやる方法もあると思うのですが、Gradleだとそれ用のプラグインがあるのでGradleを使いました。

Github

とりあえず使える状態のサンプルをGithubにおいてあります。

RobolectricGradleSample

READMEに書いてあるような状態であれば以下で実行出来るかと思います。

$gradle clean test

EclipseでRobolectricを実行させる

以下の公式サイトに丁寧に記載があるのでこちらを参照。

Eclipse Quick Start

Gradleのビルドで必要なファイルを作る

Eclipseから簡単にGradleでビルドする時に必要なファイルを出力する事が出来るので、利用します。Eclipseを起動し、以下で完了です。

File→Export→Android→Generate Gradle build files

完了すると色々ファイルが出来ていると思うので、バージョン管理に登録しておきます。

サーバー環境でAndroidをGradleでビルドする

Androidをビルド出来る環境を作る

AndroidSDKをサーバーにインストールします。自分の場合、Linuxだったので対応するSDKをダウンロードして、後は自分のビルドしたいAndoridバージョンのSDKをインストールしておきます。

この時、 AndroidSDK Build-toolsAndroid Support Repositoryもインストールしておいてください。

AndoridSDK Build-toolsはGradleのビルド時にバージョンの指定が必要なので、インストールしたバージョンも確認しておいて下さい。

なお、CUIでAndoridSDKなどのインストール方法はこちらを参照。

特定のAndroid SDKをCUIでインストールする方法

GradleをGVMを使ってインストールする

サーバーにGradleをインストールしますが、普通にインストールするとGradleのバージョン切り替えが面倒なのでGVMを使います。

GVM

インストールします。

$curl -s get.gvmtool.net | bash

現在、利用可能なGradleのバージョンを確認します。

$gvm list gradle

1.12をインストールして利用します。(Androidをビルドするためのプラグインが1.1x系を要求するため)

$gvm install gradle 1.12
$gvm use gradle 1.12

環境変数ANDROID_HOMEを設定する

GradleのAndroidプラグインにて環境変数のANDROID_HOMEを指定する必要があるので、設定します。

$vi ~/.bashrc

追加します。

# Andorid_HOME
$export ANDROID_HOME=/Applications/adt-bundle-mac-x86_64-20140624/sdk/

適用させます。

$source ~/.bashrc

Jenkinsで実行する場合、Jenkinsの環境変数を設定する箇所で上記を設定してください。

build.gradleを編集する

Eclipseでプロジェクトを新規作成するとappcompat_v7とかもコンパイルしなければいけなかったり、lib配下にandroid-support-v4.jarとかが存在します。

Eclipseでビルドする時は良いのですが、サーバーでビルドする時に上記も用意したりするのは面倒なので、Gradleを使って依存を解決します。

という事で作成されたbuild.gradleを一部編集します。 自分の場合、以下のようにしました。

// Gradle自身の環境を設定
buildscript {

    // mavenCentralリポジトリを利用する
    repositories {
        mavenCentral()
    }

    // 利用するGradleプラグインは0.13を利用
    dependencies {
        classpath 'com.android.tools.build:gradle:0.13.0'
    }
}

// すべてでmavenCentralのリポジトリを追加
allprojects {
    repositories {
        mavenCentral()
    }
}

apply plugin: 'android'

dependencies {

    compile fileTree(dir: 'libs', include: '*.jar')

    // 削除。下記のように記載することでGradleより取得
    //compile project(':appcompat_v7')

    // 追加。Gradleによってappcompatの依存関係を解決。
    // excludeの記述によってlib配下のsupport-v4との競合を避ける。
    compile ('com.android.support:appcompat-v7:18.0+') {
        exclude module: 'support-v4'
    }
}

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        // Move the tests to tests/java, tests/res, etc...
        instrumentTest.setRoot('tests')

        // Move the build types to build-types/<type>
        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
        // This moves them out of them default location under src/<type>/... which would
        // conflict with src/ being used by the main source set.
        // Adding new build types or product flavors should be accompanied
        // by a similar customization.
        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
    }
}

変更点は以下の通りです。

  • buildscriptを追加(2~13行目)
  • allprojectsを追加(16~20行目)
  • dependenciesの一部を変更(24~36行目)

buildscriptと記述されている場所はGradle自身の依存関係や利用するプラグインの情報を指定します。 今回の指定では以下2点を指定しています。

  1. buildscriptでの依存解決ではmavenCentralリポジトリを利用利用する
  2. com.android.tools.build:gradleの0.13を利用する

allprojectsと記述されている場所では以下を指定しています。

  1. 依存解決ではmavenCentralリポジトリを利用する(buildscript)

depnedenciesでは以下を指定、変更しました。

  1. appcompat_v7プロジェクトのビルドをする、という命令の箇所を削除
  2. コンパイル時に’com.android.support:appcompat-v7:18.0’以上が必要である事を記述
  3. appcompat-v7の依存を解決する時にsupport-v4に関する依存は解決しない

1点目のappcompatについてですが、Eclipseだとプロジェクトを追加した時にappcompat_v7も一緒に作成されて、ビルドが必要となります。ただし、サーバーでは面倒なので、この役目はGradleに任せる事としてコメントアウトしています。

2点目は1点目でコメントアウトしたappcompatについてGradleで依存解決する為の記述です。コンパイルする時にこのプロジェクトはappcompat-v7:18以上に依存しているよという事を記述しています。

3点目ではsupport-v4に関しての依存部分は解決しなくてよい、という事を指定しています。Gradleで依存解決を行う時は対象のものが依存しているものも一緒に依存解決しようとします。 試しにexcludeを消して、gradle dependenciesというコマンドをタイプして各ライブラリの依存関係を表示します。

$gradle dependencies 
・・・・
_debugCompile - ## Internal use, do not manually configure ##
\--- com.android.support:appcompat-v7:18.0+ -> 18.0.0
     \--- com.android.support:support-v4:18.0.0

上記のようにappcompat-v7:18はsupport-v4に依存している事が分かります。

依存解決は通常ありがたいことなのですが、今回作成したプロジェクトではlibsフォルダ配下に既にsupport-v4が存在しています。そのため、excludeしないとビルドエラーとなってしまいます。(Multiple dex files define Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCompatとか出ます。)

libs配下のsupport-v4を削除するとEclipseのビルドができなくなってしまいますので、今回は上記のように書いてありますが、Gradleでのビルド前提の場合にはGradleで依存解決は解決する方が妥当だと思います。

AndoridをGradleでビルドする

まず、自分がビルドしたいAndoridプロジェクトをサーバーに任意の場所にcloneします。

そして、build.gradleがある場所(対象のAndroidプロジェクトのRoot)に移動します。

そこで、build.gradleを開き、buildToolsVersionがサーバーでインストールしたバージョンと合っているか確認して下さい。もし、違う場合にはエラーとなるので、書き換えてください。

ANDROID_BUILD_TOOLSというような変数にしておいて、gradle.propertiesなどに設定しておく方法がおすすめです。

さて、ビルドしてみます。

$gradle build 

もし、特にエラーがなければ、build/outputs/apk配下にapkが作成されているはずです。

build.gradldを編集する2

buidl.gradleを編集してRobolectricでテスト出来るようにします。

各変更点は後述しますが、全体で以下のようになりました。

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.13.0'
        classpath 'org.robolectric:robolectric-gradle-plugin:0.13.0'
    }
}

allprojects {
    repositories {
        mavenCentral()
    }
}

apply plugin: 'android'
apply plugin: 'robolectric'

android {
    compileSdkVersion 17
    buildToolsVersion "20.0.0"

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }
        androidTest {
            setRoot('test')
        }

        // Move the tests to tests/java, tests/res, etc...
        //instrumentTest.setRoot('tests')

        // Move the build types to build-types/<type>
        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
        // This moves them out of them default location under src/<type>/... which would
        // conflict with src/ being used by the main source set.
        // Adding new build types or product flavors should be accompanied
        // by a similar customization.
        debug.setRoot('build-types/debug')
        //release.setRoot('build-types/release')
    }
}

robolectric {
    include '**/*Test.class'
}

dependencies {

    compile fileTree(dir: 'libs', include: '*.jar')
    compile ('com.android.support:appcompat-v7:18.0+') {
      exclude module: 'support-v4'
    }

    // test
    androidTestCompile('junit:junit:4.11') 
    androidTestCompile('org.robolectric:robolectric:2.3')
}

変更点は以下の通りです。

  • 依存するプラグインとしてrobolectricを追加(8,19行目)
  • テストフォルダの位置を指定(35~37行目)
  • robolectricで実行するテストクラスを指定(53~55行目)
  • テストのコンパイル時に利用するライブラリを記述(65,66行目)

自分がこの中でも特にはまったのがテストフォルダの位置を指定する箇所です。

これについてなのですが、robolectric-gradle-plugin:0.12.0までは本設定をしてもまったく有効化せず、必ずsrc/test/java配下にファイルを配置しないといけませんでした。

ただ、0.13からは任意のディレクトリの指定が可能となりました。ただし、必ず指定したディレクトリ配下にjavaというフォルダがある必要はありますので、注意が必要です。

GradleからRobolectricを実行する

早速やってみます。

$gradle clean test

gradle1.12では下記エラーになってしまいます。。。

* What went wrong:
A problem occurred evaluating root project 'RobolectricGradleSample'.
> Could not create plugin of type 'AppPlugin'.

ただし、Gradle2.1ではうまくできます。

$gvm install gradle 2.1
$gvm use gradle 2.1
$gradle clean test

こんな感じで結果がbuild/test-report/index.htmlに出力されています。

また、build/test-result/にXMLも出力されるのでこれを利用してJenkinsで実行結果のグラフ表示も可能です。

RobolectricのPluginが1.x系に対応してないからなのでしょうか。。。ちょっといまいち理由が分かっていません。知っている人がいらっしゃったら教えて頂けるとありがたいです。