ラベル git の投稿を表示しています。 すべての投稿を表示
ラベル git の投稿を表示しています。 すべての投稿を表示

2026年9月11日金曜日

コミットの author と committer をすべて指定したユーザで書き換える方法

コミットの author と committer をすべて指定したユーザで書き換える方法

概要

.git/config などを設定して無くグローバルの user,email を使ってしまっていた場合に全件 author と committer を書き換えたい場合があるかなと思います
その方法を紹介します

環境

  • macOS 26.6.2
  • git 2.55.0

書き換え

NEW_NAME="your_user_name"
NEW_EMAIL="your_user_email@local"

git stash push -u -m 'temp-before-identity-rewrite' && \
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --force --env-filter "
GIT_AUTHOR_NAME=\"$NEW_NAME\"
GIT_AUTHOR_EMAIL=\"$NEW_EMAIL\"
GIT_COMMITTER_NAME=\"$NEW_NAME\"
GIT_COMMITTER_EMAIL=\"$NEW_EMAIL\"
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
" master && \
git stash pop

確認

0 になれば OK です

git log master --format='%an%x09%ae%x09%cn%x09%ce' |
awk -F '\t' -v new_name="$NEW_NAME" -v new_email="$NEW_EMAIL" \
  '$1 != new_name || $2 != new_email || $3 != new_name || $4 != new_email { count++ }
   END { print count+0 }'

強制上書き

git push -f origin master

後処理

git update-ref -d refs/original/refs/heads/master

最後に

ちゃんと最初に .git/config は書いておきましょう

2026年8月15日土曜日

キーチェインアクセスの GUI からパスワードが消せないときの対処方法

キーチェインアクセスの GUI からパスワードが消せないときの対処方法

概要

もうキーチェインアクセスはオワコンですが git などのコマンドは未だにキーチェインアクセスを参照しているのでキーチェインアクセス側に古いパスワードが残っている場合は削除しましょう

環境

  • macOS 26.5.2
  • git 2.55.0

コマンド

security delete-internet-password -s bitbucket.org  

bitbucket.org の部分は適宜変更してください

確認

security find-internet-password -s bitbucket.org

security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain. になれば削除完了です

最後に

なぜか GUI からだと削除できないというなぞの現象が発生した場合は CLI を使いましょう

2026年2月5日木曜日

VSCode の git で認証ダイアログが定期的に出てくる場合の対処方法

VSCode の git で認証ダイアログが定期的に出てくる場合の対処方法

概要

タイトルの通りなぜか定期的に出てくるので抑制します

環境

  • Windows 11
  • VScode 1.108.2

方法

  • git config --global credential.helper cache

最後に

ただしこれでも push や pull 時には認証情報が聞かれるので注意してください
また Windows を再起動しても再度入力する必要があります

wincred とか使ってもなぜか毎回聞かれてしまいます

https の認証だとそうなるのかも

2025年4月14日月曜日

git rm で削除したファイルを復元する方法

git rm で削除したファイルを復元する方法

概要

すでにリモート側にも push している状態から復元する方法を紹介します

環境

  • git 2.47.0

ファイルとコミットハッシュの確認

  • git log -- src/utils/logger.js

復元

  • git checkout fe3c7b64cd81ae68b797a7804960accaae2fbfd4 – src/utils/logger.js

最後に

過去の実装を戻したい場合に使えます

2025年4月11日金曜日

git で管理してるファイルから拡張子の一覧を取得する方法

git で管理してるファイルから拡張子の一覧を取得する方法

概要

git ls-files を使って取得する方法を紹介します

環境

  • macOS 15.4
  • git 2.49.0

コマンド

  • git ls-files | grep -oE '\.[^.\/]+$' | sort | uniq
.el
.gitignore
.lock
.md
.rb
.ruby-version
.sh
.yasnippet
.yml

カウント数付き

  • git ls-files | grep -oE '\.[^.\/]+$' | sort | uniq -c | sort -nr
  15 .yasnippet
  13 .el
   8 .rb
   2 .yml
   2 .md
   1 .sh
   1 .ruby-version
   1 .lock
   1 .gitignore

カウントの多い順に csv にして出力する

  • git ls-files | grep -oE '\.([^.\/]+)$' | sed 's/^\.//' | sort | uniq -c | sort -nr | awk '{print $2}' | paste -sd, -

最後に

拡張子のないファイルは取得されません

2025年1月9日木曜日

git で過去のコミットから大きいファイルを探して削除する方法

git で過去のコミットから大きいファイルを探して削除する方法

概要

一度でも間違って大きいファイルを push してしまうと履歴に永遠に残るためその先のコミットで削除してもリポジトリのサイズは小さくなりません
過去の履歴から大きいファイルを削除し force push する方法を紹介します

環境

  • macOS 15.2
  • git 2.47.1

準備

  • brew install coreutils

numfmt コマンドを使えるようにします

大きいファイルの発見

git rev-list --objects --all --missing=print |
  git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' |
  sed -n 's/^blob //p' |
  sort --numeric-sort --key=2 |
  cut -c 1-12,41- |
  $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest

結果は以下のような感じでコミットハッシュ+ファイルサイズ+ファイル名で表示されます
大きいファイルは対象のコミットハッシュにあることがわかります

c31cede47e3e  741KiB libs/android-support-v4.jar
4ebdaa9ed9f3  972KiB libs/android-support-v4.jar
65adb523789c  6.4MiB app/release/app-release.aab
293e76491255  6.9MiB app/release/app-release.aab
5ffdd4c8a823  8.7MiB cert/pepk.jar
e0b9d9b10a81  602MiB java_pid4972.hprof

対象のファイルの削除

対象のリビジョンをチェックアウトし削除して force push でもいいですがそれ以降のリビジョンにも含まれるのですべてのリビジョンに対して書き換えるのが簡単です

  • git filter-branch --index-filter 'git rm --ignore-unmatch java_pid4972.hprof' --tag-name-filter 'cat' -- --all

先ほど見つけた大きいファイル名のパスを指定して上記を実行しましょう

BFG も実行する

docker run -it --rm \
  --volume "$PWD:/home/bfg/workspace" \
  koenrh/bfg \
  --strip-blobs-bigger-than 100M

filter-branch だと削除できないケースがあったので一応 BFG というツールも実行します
もしかするとこれだけでもいいかもです

BFG はファイル名ではなくファイルサイズで指定するので注意しましょう

gc

  • git reflog expire --expire=now --all && git gc --prune=now --aggressive

pack ファイルなどを削除します

force push

履歴を改変したので force push します

  • git push -f origin master

リビジョンが変わっていない場合は git commit --amend などでコメントを変えるなり reset してリビジョンを変更してから force push しましょう

履歴から大きいファイルが削除されていることの確認

先程の確認コマンドを再度実行して大きいファイルが含まれないことを確認しましょう
また以下のコマンドでリポジトリのサイズを確認しましょう

  • git count-objects -vH

それでもリモート側のサイズが小さくならない場合は

一度リモート側を削除して再度作成し push してみましょう
これでリモート側のリポジトリサイズも小さくなるはずです

ローカル側にもリモート側にも .git ファイルのキャッシュが残っておりこのサイズが大きいとリモート側も大きくなってしまいます
ローカルで小さくできたのを確認できたらリモート側のキャッシュも削除するためにリポジトリを再作成してみましょう

最後に

無料のプライベートリポジトリは大抵の場合ファイルサイズに上限があるので大きいファイルはプッシュしないようにしましょう

参考サイト

2024年9月27日金曜日

git submodule で module 側のコミットを更新する方法

git submodule で module 側のコミットを更新する方法

概要

まず大前提として git submodule は module のコミットをハッシュを管理しています
もうちょっと砕いて言うと submodule として登録したリポジトリは常に HEAD ではなく特定のコミットハッシュと紐づいています

なので git submodule update -i をしても最新の HEAD に移動しないことがあります

今回はそんな場合に submodule 側を HEAD に移動する方法を紹介します

環境

  • git 2.46.1

更新する方法

submodule のディレクトリに入って pull します
master の HEAD のコミットハッシュと新たに紐づけを行いたい場合は以下の通りです

  • cd main_repo/submodule_repo
  • git pull origin master
  • cd …
  • git status
On branch feature/test
Your branch is up to date with 'origin/feature/test'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   submodule_repo (new commits)

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

こんな感じで main_repo と submodule_repo のコミット IDの紐づけが更新される差分が出ますの状態を確認すると

git submodule コマンドで紐づいているコミットIDが確認できます

+86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 api (1.1.0-233-g61128974)

プラスマークは新たに更新されている場合に表示されます
逆にマイナスマークは紐づいているコミットIDとに齟齬がある場合に表示されます
プラスもマイナスも表示されない場合は正しいコミットIDの submodule が使われていることになります

最後に

正直 submodule はややこしいのとコミットIDの管理が面倒なので使いたくないです

参考サイト

2024年9月14日土曜日

omnibus-gitlab で管理している Prometheus のバージョンを Python から取得する方法

omnibus-gitlab で管理している Prometheus のバージョンを Python から取得する方法

概要

前回はシェルスクリプト+ gitlab ci で取得しましたが今回は Python で取得します

GitPython というライブラリを使います

環境

  • macOS 14.6.1
  • Python 3.11.10
    • GitPython 3.1.43

サンプルコード

import re
from dataclasses import dataclass

import git


# Prometheus など各種バージョンを管理するデータクラス
@dataclass
class GitlabAlertVersion:
    prometheus_version: str = ""
    alertmanager_version: str = ""
    node_exporter_version: str = ""

    # バージョン情報をファイルに保存します
    def save_to_files(self):
        with open("prometheus_version.txt", "w") as f:
            f.write(self.prometheus_version)
        with open("alertmanager_version.txt", "w") as f:
            f.write(self.alertmanager_version)
        with open("node_exporter_version.txt", "w") as f:
            f.write(self.node_exporter_version)


# omnibus-gitlab のリポジトリをクローンしてバージョンを取得するクラス
class GitlabAlertVersionFetcher:
    def __init__(self, tag="17.1.6+ee.0"):
        self.tag = tag
        self.repo_name = "omnibus-gitlab"
        self.url = f"https://gitlab.com/gitlab-org/{self.repo_name}.git"
        self.file_names = ["prometheus", "alertmanager", "node-exporter"]

    # url に記載のリポジトリを取得
    # 今回は tag を指定しシャロークローンで取得
    def _clone(self) -> git.Repo:
        return git.Repo.clone_from(
            self.url,
            f"./{self.repo_name}",
            branch=self.tag,
            depth="1",
        )

    # 指定のファイルを git grep する
    def _grep(self, file, repo: git.Repo) -> str:
        lines = repo.git.grep(
            "Gitlab::Version.new", "--", f"config/software/{file}.rb"
        ).split("\n")
        pattern = r"\d+\.\d+\.\d+"
        for line in lines:
            match = re.search(pattern, line)
            if match:
                return match.group(0)
        else:
            raise ValueError()

    # 実行メイン関数
    # file_names に定義された各種コンポーネントのバージョンを取得
    def run(self) -> GitlabAlertVersion:
        gitlab_alert_version = GitlabAlertVersion()
        repo = self._clone()
        for file in self.file_names:
            setattr(
                gitlab_alert_version,
                f"{file.replace('-', '_')}_version",
                self._grep(file, repo),
            )
        return gitlab_alert_version


if __name__ == "__main__":
    fetcher = GitlabAlertVersionFetcher()
    version: GitlabAlertVersion = fetcher.run()
    print(version)
    version.save_to_files()

最後に

GitPython を使うと git コマンドを Python 内で使うことができます

参考サイト

2024年7月4日木曜日

ansible で git credentials helper を設定する方法

ansible で git credentials helper を設定する方法

概要

git_config というビルトインモジュールがあるのでそれを使った方法を紹介します
今回は ansible を実行したユーザではなく指定のユーザにしてい git config credentials helper を設定する方法を紹介します

環境

  • Ubuntu 22.04
  • ansible 2.16.7

playbook サンプル

- name: Set config credential.helper
  git_config:
    name: credential.helper
    scope: file
    value: store
    file: /home/user01/.gitconfig

- name: Set permissions for /home/user01/.gitconfig
  file:
    path: /home/user01/.gitconfig
    group: user01
    owner: group01
    mode: '644'

ポイント

ポイントは git_config モジュールの scope に file を指定する点です
また file を使って .gitconfig を保存する場所も指定します
こうすることで ansible を実行しているユーザに対して credentials helper を設定するのではなく指定のユーザに対して設定することができます
また .gitconfig を作成したあとでユーザや権限を正しく設定してあげます
そうしないと ansible を実行したユーザの権限で .gitconfig が作成されてしまうので指定のユーザが扱えなくなってしまうためです

最後に

git_config を使って credentials helper を設定する方法を紹介しました
特定のユーザに対して設定したい場合は file を使います

直接 command などを使う方法もありますがこちらを使うほうが良いかなと思います

参考サイト

2024年7月3日水曜日

git で現在のブランチの HEAD のショートリビジョンを取得する方法

git で現在のブランチの HEAD のショートリビジョンを取得する方法
git rev-parse --short HEAD

8桁ほしい場合は

git rev-parse --short=8 HEAD

2023年12月21日木曜日

Ubuntu に最新の git をインストールする方法

Ubuntu に最新の git をインストールする方法

概要

いつも忘れるのでメモ

環境

  • Ubuntu 22.04
  • git 2.43.0

インストール方法

  • sudo add-apt-repository ppa:git-core/ppa
  • sudo apt update
  • sudo apt install git

動作確認

  • git --version
git version 2.43.0

更にバージョンアップする場合は

  • sudo apt update
  • sudo apt upgrade

メモ

すでに git がインストールされている場合でも apt remove git はしないで OK です

参考サイト

2022年4月18日月曜日

Gitlab + git push option で CI にパラメータを渡す方法

Gitlab + git push option で CI にパラメータを渡す方法

概要

Gitlab CI で「この push は CI をスキップさせたい」みたいなことがある思います
その場合には git push option を使います

環境

  • Gitlab EE 14.9.3
  • git 2.17.1

CI をスキップする

  • git push -u origin -o ci.skip master

ci.skip を指定します

特定の変数を設定する

  • git push -u origin -o ci.variable="MSG=Hello git push option" master
image: python:3.10.2-buster

stages:
  - test

test:
  stage: test
  variables:
    TZ: Asia/Tokyo
  script:
    - echo $MSG

他には

マージリクエスト関連のオプションがあります
例えば merge_request.create は自動的にマージリクエストを作成してくれます

参考サイト

2022年3月7日月曜日

git でローカルにあるブランチをすべて削除する方法

git でローカルにあるブランチをすべて削除する方法

コマンド

  • git branch | grep -v \* | xargs git branch -D

マージ前のブランチもすべて削除されます
マージ前のブランチを残したい場合は git branch --merge オプションで実行します

2020年8月4日火曜日

今更ながら git rebase をちゃんと使えるようにする

概要

git rebase はマージとは違いヘッドの位置を移動することであたかも別ブランチの修正をマージしたかのように見せます
rebase を使ったほうがコミットログがキレイになる場合があります

しかしなぜか rebase 後は force push しなければならなかったり結局マージと同じことをしている場合がありうまく使えていないことがありました
なので今更ながらちゃんと使い方を把握しておこうと思います

準備

まずは動作確認するための環境を作成します
リモートリポジトリは Github を使います

master ブランチ

  • touch memo
  • vim memo
a
  • git add .
  • git commit -m "first commit"
  • git push -u origin master

b1 ブランチの作成

master ブランチから作成します

  • git branch b1
  • git checkout b1
  • vim memo
a
b
  • git add .
  • git commit -m "second commit from b1"
  • git push -u origin b2

b2 ブランチの作成

このブランチは b1 ブランチから更に生やします

  • git branch b2
  • git checkout b2
  • vim memo
a
b
c
  • git add .
  • git commit -m "third commit from b2"
  • git push -u origin b2

でここまでのブランチごとのコミットの状況は以下のようになります

なのこの図は Github の「Insights」->「Network」から確認できます

b1 ブランチで修正が入る

  • git checkout b1
  • vim memo
a
b
d
  • git add .
  • git commit -m "thrid commit from b1"

b2 ブランチを b1 ブランチに rebase してみる (force push)

やりたいことは先程の b1 ブランチの修正を b2 ブランチにマージではなく rebase することでコミットログをキレイにします

  • git checkout b2
  • git rebase b1

何も考えずに上記を行うと当然ですがコンフリクトして rebase できません
エラーの内容は以下の感じです

Auto-merging memo CONFLICT (content): Merge conflict in memo error: could not apply a811605… third commit from b2 Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase –continue". You can instead skip this commit: run "git rebase –skip". To abort and get back to the state before "git rebase", run "git rebase –abort". Could not apply a811605… third commit from b2

ファイルにはコンフリクト部分が記載されています

a
b
<<<<<<< HEAD
d
=======
c
>>>>>>> a811605... third commit from b2

このコンフリクトを解消した上で rebase してみます

  • vim memo
a
b
c
d
  • git add .
  • git commit
  • git rebase --continue
  • git push -u origin b1

しかし以下のようにエラーが発生します

To https://github.com/hawksnowlog/test.git ! [rejected] b2 -> b2 (non-fast-forward) error: failed to push some refs to 'https://github.com/hawksnowlog/test.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: 'git pull …') before pushing again. hint: See the 'Note about fast-forwards' in 'git push –help' for details.

理由は単純でリモート側のコミットログとローカルで rebase したコミットログが異なるため push できず force push を余儀なくされている感じです
ではどうするかいうと結局 force push するしかなくなります

  • git push -f origin b2

一応これでコミットログ的には b1 の続きとして b2 が作成されていることになるのでキレイにはなります
しかし force push しなければならないので権限がない場合などこれだと対応できません

force push しないようにするには

ではコンフリクトありの rebase 時に force push しないようにするにはどうすれば良いか考えます
最初はコンフリクトしない rebase なら大丈夫かなと思ったんですが結局ローカル側のコミットID が変わってしまうようなので force push が必要になります
いろいろ考えたのですが rebase -> push を force push なしでやる場合にはリモート側にまだ push していないコミットがある場合にだけ使うしかないと思います
すでにリモート側に push しているコミットがあるブランチで rebase -> push する場合には force push は必須にするしかないと思います

Tips: やり直したい場合は

リモート側に hard reset しましょう

  • git reset --hard origin/b2

まとめ

merge と rebase の使い分けは以下の通りかなと思います

  • 基本は merge
  • リモート側にまだ push していないコミットがある場合に限り rebase
  • どうしても rebase したい場合は force push を使う

2020年5月23日土曜日

shallow clone したリポジトリを最新のコミットに追従させる方法

概要

git clone --depth 1 は shallow clone といい最新のコミット情報だけを取得することができます
clone 対象のリポジトリが大きいときなどに使います
ただこのリポジトリに対して git pull を行うとせっかく shallow clone したのにリポジトリ全体をダウンロードしてしまいます
今回は shallow clone したリポジトリを最新のコミットに変更する方法を紹介します

環境

  • Ubuntu 16.04 LTS
  • git 2.26.2

やり方

リモート側の origin/master の最新コミットに追従する場合は以下のようにします

  • git featch -u origin master
  • git reset --hard origin/master

これで shallow clone したリポジトリの最新コミットがリモート側と同じになります
ただし注意点としては shallow clone で depth 1 を指定しているので残るコミットは最新の 1 つになります
shallow clone した時点からのコミットが残るわけではないので注意しましょう

参考サイト

2018年10月25日木曜日

git credential で独自のヘルパを作ってみた

概要

前回 git-credential のビルトインの機能を使ってみました
そこでヘルパは任意のスクリプトで実装できることを知りました
今回は独自のヘルパを Ruby + Redis で作ってみました
Redis に認証情報を格納してそれを取り出し Github などの認証ができるようになります

バージョン

  • Ubuntu 18.01
  • Ruby 2.5.1p57
  • Redis 4.0.9

事前準備

  • apt -y install redis-server

ライブラリインストール

  • gem install redis

スクリプトを PATH 上に配置する関係でグローバルインストールします

ヘルパスクリプト

  • vim /usr/local/bin/git-credential-redis-helper
#!/usr/bin/env ruby

require 'redis'
require 'json'
require 'erb'
require 'securerandom'

class RedisHelper
  def initialize
    @redis = Redis.new
  end

  def list
    @redis.keys.map { |key|
      {key => @redis.get(key)}
    }
  end

  def get
    known = {}
    while line = STDIN.gets
      break if line.strip == ''
      k,v = line.strip.split '=', 2
      known[k] = v
    end
    @auth = {}
    list.each { |auths|
      auths.each { |k,v|
        auth = JSON.parse(v)
        if auth["protocol"] == known["protocol"] and auth["host"] == known["host"]
          @auth = auth
          break
        end
      }
    }
    erb = ERB.new(File.read("/usr/local/bin/auth.erb"))
    erb.result(binding)
  end

  def store
  end  

  def qstore(key, value)
    @redis.set(key, value)
  end

  def erase(key)
    @redis.del(key)
  end
end

def main
  rh = RedisHelper.new
  command = ARGV[0]
  case command
  when 'list' then
    puts rh.list
  when 'get' then
    puts rh.get
  when 'store' then
    rh.store
  when 'qstore' then
    rh.qstore(ARGV[1], ARGV[2])
  when 'erase' then
    rh.erase(ARGV[1])
  else
  end
end
  • chmod 755 /usr/local/bin/git-credential-redis-helper

拡張子なしで作成するためシェバングを付与しています
git からコールされるため実行権限を付与します

説明

main 関数を用意したのでそこから見ると良いと思います
引数のコマンドに応じて redis に対する処理が変わってきます

get

必ず実装しなければいけないのが get です

get は標準入力を受け取って、その入力条件に当てはまる認証情報を redis から取得します
そして決められたフォーマットで認証情報を標準出力します
今回の redis のフォーマットは SET を使って key + hash として認証情報を登録することを想定しています
hash 側に認証情報があるのでそこと比較して当てはまるものがあれば erb でフォーマットして出力している感じです

redis に登録する際のフォーマットは改良の余地ありかなと思います
また、erb も必須ではありません
改行などもあるので、今回は使いましたが直接 puts しても問題ないです

qstore

引数に key + hash を取りそれをそのまま redis に格納します
store とコマンド名がかぶらないように q を付与しています

list

list は確認用の便利コマンドとして用意しました
redis 内にあるすべての key 情報に対してデータを取得して表示してくれます

erase

指定の key を redis から削除してくれます

store

不明
後で実行方法を紹介しますが、おそらくこれがちゃんと実装されていれば一度目の認証情報をちゃんと redis に格納できるようになるんだと思います

テンプレートファイルの配置

  • vim /usr/local/bin/auth.erb
protocol=<%= @auth["protocol"] %>
host=<%= @auth["host"] %>
username=<%= @auth["username"] %>
password=<%= @auth["password"] %>

これは正直なくてもいいかもしれません
直接スクリプト内で puts しても OK です

動作確認 (使い方)

redis-server は起動しておきましょう
また現状は localhost:6379 でのみ動作していることを想定しています

まず認証情報を登録します

git credential-redis-helper qstore 'github' '{"protocol":"https","host":"github.com","username":"hawksnowlog","password":"xxxxxxxx"}'

こんな感じです
別に Github の情報でなくても OK です
登録した認証情報は list コマンドで確認できます

  • git credential-redis-helper list

また git credential-redis-helper get はインタラクティブに認証情報を検索することができます
これは store や cache ヘルパと同じ仕様になります

登録したら認証が聞かれるか確認してみましょう
Github の場合であれば push 時に認証が聞かれなければ OK です

登録した認証情報を削除したい場合は

  • git credential-redis-helper erase github

で可能です
もちろん redis-cli でログインして DEL しても OK です

最後に

git credential で独自のヘルパスクリプトを実装してみました
今回は Ruby + Redis で開発しましたが、同じように別の言語や RDB でも実装可能です
store の挙動がよくわからなかったので今回の仕様では事前に redis に認証情報を登録する必要が出てしましました
本来は一度目の認証を redis に登録してそれ以降は redis にある認証情報を使いたかったのです

その辺りの問題を解決して、もう少しリファクタリングすれば公開できるかなと思います (ホスト名の指定やパスワード情報の暗号化なども実装したほうが良いかなと思います)
redis をインストールする必要もあるので需要があるか不明ですが

2018年10月24日水曜日

git credential を使おう

概要

git の認証を毎回入力するのは面倒なので localhost 上に認証情報を保存することができます
今回は基本的な使い方を紹介します

環境

  • Ubuntu 16.04
  • git 2.7.4

永続的に保存 (store)

認証情報をファイルに保存する方法です
認証情報が消えることはないので登録すればそれ以降はパスワードを尋ねられることはないですが残念ながら保存方法が平文しかありません

永続的に保存する場合は store を使います

  • git config --global credential.helper store
  • cat ~/.gitconfig
[credential]
        helper = store

これで store を使う準備ができました
あとは認証情報を記載したファイルを作成するだけです

  • git credential-store store

で対話的に登録することができます
以下のような感じで入力していけば OK です

protocol=https
host=github.com
username=hawksnowlog
password=xxxxxxxxxxxxxx

Ubuntu の場合、認証情報が登録されるデフォルトのファイルは ~/.git-credentials になります
中身を確認すると平分で保存されているのが分かると思います

https://hawksnowlog:xxxxxxxxxxxxxx@github.com
  • git credential fill

で対話的に認証情報を検索することもできます

暗号化するには

とは言えパスワード情報なので暗号化したくなるので普通です
その場合には git-credential-libsecret を使います
ただこれを条件として

  • Xserver が必要
  • git の 2.11+ が必要

があります
なので使える状況としてはデスクトップ Ubuntu として使っている場合かなと思います

一応使う場合は以下の通りです
まず Ubuntu で git の最新版を使えるようにします

  • add-apt-repository ppa:git-core/ppa
  • apt -y install git

これで最新版が使えるようになります
あとは libsecret helper を作成し登録します

  • make --directory=/usr/share/doc/git/contrib/credential/libsecret/
  • git config --global credential.helper /usr/share/doc/git/contrib/credential/libsecret/git-credential-libsecret
  • cat ~/.gitconfig
[credential]
        helper = /usr/share/doc/git/contrib/credential/libsecret/git-credential-libsecret

これで一度パスワードを聞かれたあとに認証情報を入力すれば、その後は聞かれなくなると思います

ちなみに Mac で Github などに認証するときにパスワードを聞かれなくなるのは osxkeychain という helper を使っているためです

  • git config --list
credential.helper=osxkeychain

macOS に含まれてる「キーチェーンアクセス」という認証情報を管理する仕組みを使っています
キーチェーンアクセスを開いて保存されているパスワードの一覧を開くと Github の認証が保存されているのを確認できると思います
git_credential1.png

Tips: git-credential-gnome-keyring は deprecated になっている

以下の方法は deprecated になっているようです

  • apt install -y libgnome-keyring-dev
  • make --directory=/usr/share/doc/git/contrib/credential/gnome-keyring
  • git config --global credential.helper /usr/share/doc/git/contrib/credential/gnome-keyring/git-credential-gnome-keyring

一時的に保存 (cache)

認証情報をメモリに一時的に保存する方法もあります
デーモンが常駐しそのデーモンが認証情報をキャッシュしてくれます
指定された timeout が過ぎると自動的に認証情報が削除されます
helper に cache を登録すれば完了です

  • git config --global credential.helper cache
  • cat ~/.gitconfig
[credential]
       helper = cache

timeout のデフォルトは 900sec (15miin) になっているようです
--timeout で指定することもできます

  • git config --global credential.helper cache --timeout 30000

cache の場合指定時間で認証情報は消えてしまいますが store のように平文ファイルを作らないため安全です
また緊急で全キャッシュを削除したい場合は

  • git credential-cache exit

で可能です

実は helper は自分で作れる

これまでビルトインである store と cache を紹介しましたが同じように自分でも helper を作ることはできます
git 側で決められたフォーマットで出力すれば良いだけなので簡単に作れます
このページに簡単な Ruby のスクリプトヘルパもあります

例えば認証情報を格納した json ファイルからパスワードを取り出して認証させるみたいなヘルパを作成することもできます

この辺の git のアーキテクチャは素晴らしいなと思いました

最後に

git-credential を使ってみました
ヘルパという外部のプログラムと連携することで認証情報を任意の場所に補完して取り出すことができるようになります
ビルトインは store と cache が使えるようです

またヘルパは独自で作成することもできます
認証情報をすでに管理している仕組みがあるのであればそこにアクセスして取ってくるみたいなことができるようになります

参考サイト

2017年3月10日金曜日

CentOS6 で Git2 をインストールする方法

概要

CentOS6 で Git のバージョン2 系をインストールしてみました
既存の git は yum でインストールしているので一旦削除してからインストールします

環境

  • CentOS 6.7 Final
  • git 2.7.2

インストール方法

既存の git を削除

  • yum remove git

Git2 をインストール

  • yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
  • wget https://www.kernel.org/pub/software/scm/git/git-2.7.2.tar.gz
  • tar zvxf git-2.7.2.tar.gz
  • cd git-2.7.2
  • make prefix=/usr/local all
  • make prefix=/usr/local install
  • git --version

今回は prefix で /usr/local を指定しているため PATH が通っていない場合は通してください
PATH が通っていても反映されない場合は一度ログアウトして再度ログインしてみてください