自作のToDoアプリ(FastAPI + React)を、.env やデータベースなどの秘密情報を除外して安全な形でGitHubに公開した手順です。
今回の環境
| 項目 | 内容 |
|---|---|
| OS | Windows 11 Home |
| ターミナル | Git Bash(Gitのコマンド)/PowerShell |
| Git | 2.51.0.windows.2 |
| 公開したもの | FastAPI + React のToDoアプリ(バックエンド・フロントエンド一式) |
| 公開先 | GitHub(Publicリポジトリ) |
公開してはいけないファイル
プロジェクトのフォルダを点検したところ、次のファイルが見つかりました。どれもGitHubに上げてはいけないものです。
| ファイル | 中身 |
|---|---|
backend/.env | JWT署名用の SECRET_KEY などの設定値 |
backend/.secret_key | 開発時に自動生成された秘密鍵 |
backend/todo.db | SQLiteのデータベース(ユーザー情報・自分のタスク) |
backend.zip / frontend.zip | 作成した覚えのないZIP。backend.zip の中に .env、.secret_key、todo.db が入っていた |
chat-summary.md | 非公開ページへのリンクを含むメモ |
ToDoアプリ_仕様書.docx | 公開不要の仕様書 |
ZIPの中身は、次のコマンドで確認できます(Git Bashで実行)。
python -c "
import zipfile
for f in ['backend.zip','frontend.zip']:
n=zipfile.ZipFile(f).namelist(); print(f, len(n),'entries')
print([x for x in n if any(k in x.lower() for k in ('.env','secret','.db','.key','node_modules','.venv'))][:15])
"
.gitignore とは?
Gitに「このファイルは管理しない(GitHubにも上げない)」と伝えるための設定ファイルです。プロジェクトのフォルダ直下に置きます。
GitHubに公開する手順
手順1:.gitignore を書く
プロジェクト直下に .gitignore を作り、次の内容にしました。秘密情報とデータベースに加えて、ZIPや出所のわからないファイルも除外しています。
# --- 秘密情報(公開しない) ---
.env
.env.*
!.env.example
.secret_key
*.pem
*.key
# --- データベース(ユーザー情報・個人のタスクを含む) ---
*.db
*.sqlite
*.sqlite3
# --- 生成物・依存 ---
__pycache__/
*.pyc
.venv/
node_modules/
dist/
.pytest_cache/
# --- 公開不要・秘密が混入しているファイル ---
*.zip
*.docx
chat-summary.md
!.env.example は「.env.example だけは除外しない」という意味です。.env.example は設定項目の雛形で、値は空にしてあります。
# このファイルを .env にコピーして値を設定する(.env はGit管理外)
# PostgreSQL 接続先。未設定の場合は backend/todo.db(SQLite)を使う
DATABASE_URL=postgresql://todo:your-password@localhost:5432/todo
# JWT署名用の秘密鍵(本番は必須)
# python -c "import secrets;print(secrets.token_urlsafe(48))"
SECRET_KEY=
# フロントエンドのオリジン(カンマ区切り)
CORS_ORIGINS=http://localhost:5173
手順2:ローカルリポジトリを作り、追加されるファイルを確認する
Git Bashでプロジェクトのフォルダに移動し、リポジトリを作って全ファイルを追加します。git ls-files で、コミットされる予定のファイルを一覧にします。
cd "プロジェクトのフォルダ"
git init -b main
git add -A
git ls-files
一覧を目で見るだけでなく、危ないファイル名が含まれていないかを grep で検索します。何も表示されなければOKです。
git ls-files | grep -Ei '(^|/)\.env$|secret_key|\.db$|\.zip$|\.docx$|chat-summary|\.venv|node_modules|dist/'
git add のときに LF will be replaced by CRLF という警告が大量に出ましたが、Windowsの改行コードに関する警告で、問題はありません。
手順3:ファイルの中身に秘密の値がないか検索する
ファイル名だけでなく、中身も検索します。git grep --cached は、git add したファイルの中身を検索するコマンドです。.env に書いてある実際の鍵の一部や、自分の名前・IDで検索しました。
git grep --cached -n "実際の鍵の一部"
echo $?
git grep --cached -nEi "自分の名前|自分のID|非公開ページのURL"
echo $?
echo $? は直前のコマンドの終了コードを表示します。git grep は、見つからなければ 1、見つかれば 0 を返します。私の場合はどちらも 1(該当なし)でした。
「|| echo 問題なし」の確認は危ない
最初は git grep -n "鍵" --cached || echo "含まれていません" のように書いていました。ところがオプションの位置が間違っていて、fatal: option '--cached' must come before non-option arguments で失敗していたのに、「含まれていません」と表示されていました。|| の後ろは、検索で見つからなかったときだけでなく、コマンド自体が失敗したときにも実行されます。確認用のコマンドは、終了コードまで見るようにしてください。
手順4:GitHubアカウントを作り、メールアドレスを非公開にする
- GitHubのサイトで「Sign up」からアカウントを作る
- 右上のアイコン →「Settings」→「Emails」を開く
- 「Keep my email addresses private」にチェックを入れる
- 表示される身代わりのアドレス(
<ID>+<ユーザー名>@users.noreply.github.com)をメモする
なぜメールアドレスを隠すのか
Gitのコミットには、作者のメールアドレスが記録されます。Publicリポジトリでは誰でも見られるので、普段使いのアドレスが公開されてしまいます。GitHubの設定だけでは不十分で、次の手順でGit側にも身代わりのアドレスを設定する必要があります。
手順5:Gitに名前とメールアドレスを設定する
git config --global user.name "<ユーザー名>"
git config --global user.email "<ID>+<ユーザー名>@users.noreply.github.com"
手順6:最初のコミットを作る
git commit -m "Initial commit"
手順7:GitHubに空のリポジトリを作る
GitHubの右上「+」→「New repository」から、リポジトリを作ります。
- Repository name:
todo-app - 公開範囲:Public
- README・.gitignore・ライセンスは追加しない(空のリポジトリにする)
手順8:GitHubにpushする
git remote add origin https://github.com/<ユーザー名>/todo-app.git
git push -u origin main
初回の git push では、ブラウザに「Authorize git-ecosystem」という認証画面が開きました。これはGitに同梱されている公式の認証ツール(Git Credential Manager)の画面です。直前に自分で git push を実行したのであれば、承認して大丈夫です。
動作確認:公開された内容を確認する
コミットに記録されたメールアドレスが身代わりのアドレスになっているかを確認します。
git log --format='%h | %an | %ae | %cn | %ce | %s'
作者(%ae)とコミッター(%ce)の両方が …@users.noreply.github.com になっていればOKです。
次に、GitHub側に公開されたファイルの一覧と、公開範囲をAPIで確認します。ブラウザの画面だけで判断せず、ファイル名を一覧で見るのが確実です。
# 公開されたファイルの一覧
curl -s "https://api.github.com/repos/<ユーザー名>/todo-app/git/trees/main?recursive=1" | grep '"path"'
# 公開範囲(private と visibility)
curl -s https://api.github.com/repos/<ユーザー名>/todo-app | grep -E '"private"|"visibility"'
私の場合、公開されたファイルは62件で、名前で引っかかったのは backend/.env.example(中身は雛形)だけでした。公開範囲は "private": false、"visibility": "public" でした。
つまずいたところ
公開不要のメモ(SESSION_NOTES.md)までpushしていた
作業内容をまとめた SESSION_NOTES.md(設計メモ)を、そのまま公開してしまいました。秘密の値は入っていませんでしたが、公開する必要のないファイルです。
ほかのファイルから参照されていないことを確認してから、削除してpushしました。
git grep -n "SESSION_NOTES"
git rm SESSION_NOTES.md
git commit -m "Remove SESSION_NOTES.md"
git push
これで最新の状態からは消えますが、過去のコミット(Initial commit)にはファイルが残ったままです。
履歴を作り直して強制pushした
履歴からも消すために、コミット履歴を1から作り直して、GitHub側を強制的に上書きしました。
cd "プロジェクトのフォルダ"
git status
git checkout --orphan clean-main
git add -A
git commit -m "Initial commit"
git branch -D main
git branch -m main
git push -f origin main
実行後、ローカル・GitHubともにコミットは「Initial commit」の1件だけになり、SESSION_NOTES.md も一覧から消えました(ファイルは61件)。
強制pushしても、古いコミットは番号指定で見られた
念のため、古いコミットの番号を指定してアクセスしてみました。
curl -s -o /dev/null -w "%{http_code}\n" "https://api.github.com/repos/<ユーザー名>/todo-app/commits/<古いコミット番号>"
curl -s -o /dev/null -w "%{http_code}\n" "https://raw.githubusercontent.com/<ユーザー名>/todo-app/<古いコミット番号>/SESSION_NOTES.md"
結果は、どちらも 200(取得できる)でした。GitHubは、ブランチから外れたコミットをすぐには削除せず、後で自動的に整理する仕組みのようで、main の履歴から消えても、番号を知っていれば中身を見られる状態でした。
完全に消したい場合の選択肢は、次の3つです。
- リポジトリを削除して同じ名前で作り直し、
git push -u origin mainする(確実) - GitHubサポートに、参照されないコミットの削除を依頼する(URLは変わらない)
- GitHubが自動で整理するのを待つ(時期はわからない)
今回のファイルは設計メモで、セキュリティ上問題のある内容は含まれていなかったため、古いコミットはそのままにしました。もし鍵やパスワードをpushしてしまった場合は、履歴の削除に頼らず、鍵やパスワードそのものを新しく作り直す必要があります。
まとめ
.env、秘密鍵、データベースは.gitignoreで除外する- ZIPや出所のわからないファイルは、公開前に中身を確認する
git addの後、git ls-filesとgit grep --cachedで、ファイル名と中身の両方を点検する- 確認用のコマンドは、
|| echoに頼らず終了コードまで見る - コミットのメールアドレスは、GitHubの設定と
git configの両方で身代わりのアドレスにする - 公開後はAPIでファイル一覧と公開範囲を確認する
- 強制pushしても、古いコミットはしばらくGitHubに残る。一度pushした鍵やパスワードは作り直す
今回公開したToDoアプリのGitHubリンクでs。
👉 【todo-app】(GitHub)


コメント