অধ্যায় 2 · Git ও GitHub
.gitignore: সিক্রেট আর অপ্রয়োজনীয় ফাইল বাইরে রাখা
- পৃষ্ঠা 6 / 22
- 16 মিনিট পড়া
একটা AI প্রজেক্ট ফোল্ডার খুব দ্রুত এমন সব জিনিসে ভরে ওঠে যা কখনোই Git-এ যাওয়া উচিত নয়: আপনার OpenAI বা Anthropic API কি-সহ একটা .env ফাইল, হাজার হাজার লাইব্রেরি ফাইলের একটা .venv ফোল্ডার, __pycache__-এর জঞ্জাল, ২ জিবির একটা ট্রেনিং CSV, একটা ট্রেইন করা মডেল ফাইল, নোটবুকের চেকপয়েন্ট। এর কোনোটা কমিট করলে সবচেয়ে ভালো ক্ষেত্রেও রিপোজিটরি ধীর আর ফোলা হয়ে যায়, আর সবচেয়ে খারাপ ক্ষেত্রে ফাঁস হওয়া একটা API কি দিয়ে কেউ আপনার নামে বিল তুলতে থাকে।
এটা ঠেকানোর হাতিয়ার একটাই ছোট টেক্সট ফাইল — .gitignore। এই পাতায় দেখবেন AI প্রজেক্টের জন্য কেমন একটা লিখবেন, সেটা সত্যিই কী করছে তা কীভাবে যাচাই করবেন, কিছু আগেই কমিট হয়ে গেলে কী করবেন, আর কেন যে সিক্রেট একবার কমিটে গেছে তাকে ফাঁস হয়ে যাওয়া ধরে নিতে হয়।
যা শিখবেন
.gitignoreকী করে, আর প্যাটার্নের নিয়ম: নাম, ফোল্ডার,*,**, শুরুর/, আর!ব্যতিক্রম।- AI প্রজেক্টের জন্য কাজের একটা
.gitignore:.env,.venv,__pycache__, ডেটা, মডেল ফাইল, নোটবুক চেকপয়েন্ট। .env+.env.exampleপ্যাটার্ন, যাতে টিমমেটরা আপনারটা না দেখেও জানতে পারে কোন সেটিং দিতে হবে।git check-ignore -vআরgit status --ignoredদিয়ে নিয়ম ডিবাগ করা।- আগেই কমিট হয়ে যাওয়া ফাইল আনট্র্যাক করা (
git rm --cached), আর কেন কমিট হওয়া সিক্রেট মানেই ফাঁস হওয়া সিক্রেট।
উদাহরণ প্রজেক্ট সাজানো
এই অধ্যায়ের প্রতিটা পাতা একটা ফাঁকা হোম ফোল্ডার থেকে শুরু হয়, তাই আগে একটা ছোট প্রজেক্ট বানাই: কয়েকটা নমুনা রিভিউসহ কিওয়ার্ড-ভিত্তিক রিভিউ সেন্টিমেন্ট অ্যানালাইজার। এখানকার প্রতিটা কমান্ড আপনি আগের দুটো পাতা থেকে চেনেন; -q (quiet) শুধু git init আর git commit-এর স্বাভাবিক বার্তা ছাপা বন্ধ রাখে। প্রথম দিনেই নাদিয়া তার প্রথম "ট্রেইন করা মডেল" models/-এ সেভ করে কমিটও করে ফেলেছিল, ভালো করে জানার আগেই। (মডেল ফাইলটা ছদ্মবেশী: আসল ওয়েটের বদলে কয়েক বাইট।)
mkdir -p ~/projects/review-analyser
cd ~/projects/review-analyser
git init -q
cat > analyse.py <<'EOF'
"""Label product reviews as positive, negative or neutral with two small word lists."""
import csv
POSITIVE = {"good", "great", "fast", "love", "excellent"}
NEGATIVE = {"bad", "slow", "broken", "late", "terrible"}
def label(text):
words = text.lower().split()
score = sum(w in POSITIVE for w in words) - sum(w in NEGATIVE for w in words)
return "positive" if score > 0 else "negative" if score < 0 else "neutral"
if __name__ == "__main__":
with open("reviews.csv", newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
print(label(row["text"]), "|", row["text"])
EOF
cat > reviews.csv <<'EOF'
id,text
1,great phone and fast delivery
2,battery is bad and the box was broken
3,it works
EOF
mkdir -p models
printf 'stand-in for trained weights v1\n' > models/sentiment-v1.joblib
git add .
git commit -q -m "Add keyword review analyser, sample reviews and first model"
python analyse.pypositive | great phone and fast delivery
negative | battery is bad and the box was broken
neutral | it worksএকটা আসল AI প্রজেক্ট যে জঞ্জাল বানায়
এবার প্রজেক্টটাকে বাড়তে দিই, আসল প্রজেক্ট যেভাবে বাড়ে। নিচের প্রতিটা লাইন এমন কিছু বানায় যা প্রায় প্রতিটা AI রিপোজিটরিতে পাবেন:
python -m venv .venv # একটা ভার্চুয়াল এনভায়রনমেন্ট (হাজার হাজার ফাইল)
rm -f .venv/.gitignore # Python 3.13+ এই ফাইলটা যোগ করে; নিচের নোট দেখুন
python -m py_compile analyse.py # import করলে যা হয়: __pycache__/ তৈরি হয়
mkdir -p data/raw data/sample notebooks/.ipynb_checkpoints
python -c "
rows = ['id,text'] + [f'{i},sample review {i}' for i in range(1, 200001)]
open('data/raw/reviews-full.csv', 'w').write('\n'.join(rows) + '\n')
"
head -n 3 data/raw/reviews-full.csv > data/sample/reviews-sample.csv
echo '{"cells": []}' > notebooks/explore.ipynb
echo '{"cells": []}' > notebooks/.ipynb_checkpoints/explore-checkpoint.ipynb
cat > .env <<'EOF'
OPENAI_API_KEY=sk-proj-EXAMPLE-not-a-real-key
DATABASE_URL=postgresql://nadia:hunter2@db.example.com/reviews
EOF
git statusOn branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
.env
.venv/
__pycache__/
data/
notebooks/
nothing added to commit but untracked files present (use "git add" to track)Git পাঁচটা আনট্র্যাকড এন্ট্রি দেখছে, আর এর মধ্যে সামান্য অংশই (নোটবুক আর ডেটা নমুনা) রিপোজিটরিতে থাকার যোগ্য। এখন একটা অসতর্ক git add . আপনার API কি, ৪ এমবির একটা ডেটা ফাইল আর একটা গোটা Python ইনস্টলেশন কমিট করে দেবে। (মডেল ফাইলটা তালিকায় নেই কারণ সেটা আগে থেকেই ট্র্যাকড; পরে সেটা আবার আসবে।) "আসল" ডেটা কত বড় তা wc দেখিয়ে দেয়:
wc -l data/raw/reviews-full.csv200001 data/raw/reviews-full.csv
.venvপ্রসঙ্গে: Python 3.13 থেকেpython -m venv(এবংuv venv) নতুন এনভায়রনমেন্টের ভেতরে*লেখা এক লাইনের একটা.gitignoreবানায়, ফলে Git নিজেই সেটা উপেক্ষা করে। আমরা উপরে ওই ফাইলটা মুছেছি, যাতে আপনার Python যেটাই হোক সবাই একই আউটপুট দেখে। তবু আপনার প্রজেক্টের.gitignore-এ.venv/রাখুন: পুরোনো Python,virtualenvআর conda এনভায়রনমেন্ট এমন ফাইল বানায় না।
.gitignore লেখা
.gitignore রিপোজিটরির রুটে থাকা একটা সাদামাটা টেক্সট ফাইল, প্রতি লাইনে একটা প্যাটার্ন। যে আনট্র্যাকড ফাইল কোনো প্যাটার্নের সাথে মেলে Git সেটা এড়িয়ে যায়: git status থেকে সেগুলো উধাও হয়ে যায় আর git add . সেগুলো তুলবে না। ফাইলটা নিজে কিন্তু কমিট হয়, তাই প্রতিটা টিমমেট আর প্রতিটা ক্লোন একই নিয়ম পায়। এডিটরে বানান (প্রথম লাইনটা একটা কমেন্ট):
# file: .gitignore
# Secrets: never commit these
.env
.env.*
!.env.example
# Python
__pycache__/
*.py[cod]
.venv/
venv/
# Jupyter
.ipynb_checkpoints/
# Data and models: too big for Git, stored and versioned elsewhere
data/*
!data/sample/
models/
*.joblib
*.pt
*.safetensorsgit statusOn branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
data/
notebooks/
nothing added to commit but untracked files present (use "git add" to track)এখন মাত্র তিনটা জিনিস বাকি: .gitignore নিজে, data/ (কারণ data/sample/-এর ব্যতিক্রম) আর notebooks/ (কারণ explore.ipynb)। সিক্রেট, এনভায়রনমেন্ট, বাইটকোড, বড় CSV আর চেকপয়েন্ট কপি চোখের সামনে থেকে সরে গেছে। আরও লক্ষ করুন, যা নেই: models/sentiment-v1.joblib। এটা models/-এর সাথে মেলে, কিন্তু নিয়মটা আসার আগেই কমিট হয়ে গেছে। কথাটা মনে রাখুন; নিচে আবার ফিরব।
প্যাটার্নের নিয়ম
| প্যাটার্ন | কীসের সাথে মেলে | ব্যবহারের উদাহরণ |
|---|---|---|
.env | যেকোনো ফোল্ডারে ওই নামের ফাইল বা ফোল্ডার | সিক্রেট ফাইল |
models/ | শেষে / মানে শুধু ফোল্ডার (এবং তার ভেতরের সবকিছু) | মডেল চেকপয়েন্ট |
*.joblib | * মানে / ছাড়া যেকোনো অক্ষরের সারি | যেকোনো জায়গার সেভ করা scikit-learn মডেল |
*.py[cod] | [cod] সেট থেকে একটা অক্ষর: .pyc, .pyo, .pyd | কম্পাইল করা Python |
/output.csv | শুরুর / প্যাটার্নকে .gitignore-এর ফোল্ডারে আটকে দেয় (এখানে শুধু রুটে) | স্ক্রিপ্ট রুটে যে ফাইল লেখে |
data/* | data/-এর সরাসরি ভেতরের সবকিছু (মাঝখানে / থাকলেও প্যাটার্ন আটকে যায়) | কাঁচা ডেটা |
**/checkpoints/ | ** মানে "যেকোনো সংখ্যক ফোল্ডার" | যেকোনো গভীরতার চেকপয়েন্ট ফোল্ডার |
!.env.example | ! আগের প্যাটার্নে বাদ পড়া কিছু ফিরিয়ে আনে | সেটিংসের টেমপ্লেট |
# text | কমেন্ট; ফাঁকা লাইনও উপেক্ষিত হয় | নিয়ম ব্যাখ্যা করা |
দুটো নিয়ম জটিল ক্ষেত্রগুলো ঠিক করে। প্রথম, শেষে মেলা প্যাটার্নই জেতে; এ কারণেই !.env.example বসেছে .env.*-এর পরে। দ্বিতীয়, কোনো ফাইলের প্যারেন্ট ফোল্ডার বাদ পড়লে Git তাকে আর ফিরিয়ে আনতে পারে না: data/ লিখলে Git ফোল্ডারের ভেতরে তাকায়ই না, তাই !data/sample/ কিছুই করবে না। এজন্যই ফাইলে লেখা data/* (data/-এর ভেতরের জিনিস উপেক্ষা করো) আর তারপর data/sample/-এর জন্য ব্যতিক্রম।
কী উপেক্ষিত হচ্ছে, আর কেন — যাচাই করা
কোনো ফাইল উপেক্ষিত হচ্ছে অথচ কেন জানেন না (বা উপেক্ষিত হওয়া উচিত অথচ হচ্ছে না), তখন Git-কে জিজ্ঞেস করুন। git check-ignore -v ফাইল, লাইন নম্বর আর যে প্যাটার্ন সিদ্ধান্ত নিয়েছে সেটা ছাপে:
git check-ignore -v .env data/raw/reviews-full.csv .venv __pycache__ notebooks/.ipynb_checkpoints.gitignore:3:.env .env
.gitignore:17:data/* data/raw/reviews-full.csv
.gitignore:10:.venv/ .venv
.gitignore:8:__pycache__/ __pycache__
.gitignore:14:.ipynb_checkpoints/ notebooks/.ipynb_checkpointsযে ফাইল উপেক্ষিত নয় তার জন্য কিছুই ছাপা হয় না, আর কমান্ড স্ট্যাটাস ১ দিয়ে বের হয়। তবু তালিকায় দেখতে চাইলে -n (--non-matching) যোগ করুন:
git check-ignore -v -n data/sample/reviews-sample.csv .env.example:: data/sample/reviews-sample.csv
.gitignore:5:!.env.example .env.example:: মানে "কোনো প্যাটার্ন এই ফাইলের সাথে মেলে না": নমুনা ফাইলটা মোটেই উপেক্ষিত নয়, কারণ !data/sample/ ব্যতিক্রম তার ফোল্ডারটাকে ইগনোর হতে দেয়নি। .env.example একটা প্যাটার্নের সাথে মিলেছে, কিন্তু সেটা ৫ নম্বর লাইনের ! ব্যতিক্রম, আর ! দিয়ে শুরু প্যাটার্নের মানে "উপেক্ষা কোরো না"। পুরো ছবির জন্য git status --ignored উপেক্ষিত ফাইলও দেখায়; সংক্ষিপ্ত রূপে ?? মানে আনট্র্যাকড আর !! মানে উপেক্ষিত:
git status --short --ignored?? .gitignore
?? data/
?? notebooks/
!! .env
!! .venv/
!! __pycache__/
!! data/raw/
!! notebooks/.ipynb_checkpoints/Git দুর্ঘটনা থেকেও আগলে রাখে। কোনো উপেক্ষিত ফাইলের নাম সরাসরি দিলে git add রাজি হয় না:
git add .envThe following paths are ignored by one of your .gitignore files:
.env
hint: Use -f if you really want to add them.
hint: Turn this message off by running
hint: "git config advice.addIgnoredFile false"git add -f জোর করে ঢোকাতে পারে। সিক্রেট ফাইলের ক্ষেত্রে উত্তর সহজ: করবেন না।
.env আর .env.example
আপনার কোডের আসল সেটিং দরকার, কিন্তু রিপোজিটরিতে তা থাকা চলবে না। প্রচলিত সমাধান, যা আপনি এনভায়রনমেন্ট ভেরিয়েবল, .env ফাইল ও ভার্চুয়াল এনভায়রনমেন্ট পাতায় দেখেছেন, দুটো ফাইল:
.env: আপনার মেশিনের আসল মান। উপেক্ষিত, Git দিয়ে কখনো শেয়ার হয় না।.env.example: একই ভেরিয়েবলের নাম, কিন্তু নমুনা মান। কমিট করা হয়, যাতে টিমমেট (বা নতুন ল্যাপটপে আপনি নিজে) জানতে পারে কী ভরতে হবে:cp .env.example .env, তারপর এডিট।
cat > .env.example <<'EOF'
# Copy to .env and fill in real values. Never commit .env.
OPENAI_API_KEY=your-key-here
DATABASE_URL=postgresql://user:password@localhost/reviews
EOF
git check-ignore -q .env.example || echo ".env.example will be committed"
git check-ignore -q .env && echo ".env stays private".env.example will be committed
.env stays private(-q কিছু ছাপে না, শুধু এক্সিট স্ট্যাটাস সেট করে — স্ক্রিপ্টে কাজের।) প্রোগ্রাম আসল মান পড়ে এনভায়রনমেন্ট থেকে, কখনোই সোর্স কোড থেকে নয়। python-dotenv দিয়ে load_dotenv(".env") ফাইলের মানগুলো os.environ-এ কপি করে (পাথ না দিলে এটা স্ক্রিপ্টের নিজের ফোল্ডার থেকে শুরু করে .env খোঁজে):
import os
from dotenv import load_dotenv
load_dotenv(".env") # মানগুলো os.environ-এ কপি করে
key = os.environ["OPENAI_API_KEY"]
print("key loaded:", key[:8] + "...") # পুরো কি কখনো প্রিন্ট বা লগ করবেন নাkey loaded: sk-proj-...এবার সবকিছু স্টেজ করে দেখুন কী কমিট হবে। নিয়মগুলোর কল্যাণে git add . আবার নিরাপদ:
git add .
git status --shortA .env.example
A .gitignore
A data/sample/reviews-sample.csv
A notebooks/explore.ipynbgit commit -m "Ignore secrets, environments, data and models; add .env.example"[main 7155cf8] Ignore secrets, environments, data and models; add .env.example
4 files changed, 29 insertions(+)
create mode 100644 .env.example
create mode 100644 .gitignore
create mode 100644 data/sample/reviews-sample.csv
create mode 100644 notebooks/explore.ipynbআগেই কমিট হয়ে গেছে? .gitignore সাহায্য করবে না
.gitignore শুধু আনট্র্যাকড ফাইলে কাজ করে। Git যে ফাইল ইতিমধ্যে ট্র্যাক করছে, নিয়ম যা-ই বলুক, সেটা ট্র্যাকড থাকে। দেখুন: নাদিয়া তার মডেল আবার ট্রেইন করে, আর models/ .gitignore-এ থাকা সত্ত্বেও Git পরিবর্তনটা জানায়:
printf 'stand-in for trained weights v2\n' > models/sentiment-v1.joblib
git status --short M models/sentiment-v1.joblibট্র্যাকিং থামাতে ফাইলটা ইনডেক্স (স্টেজিং এরিয়া) থেকে সরান, ডিস্ক থেকে নয় — git rm --cached দিয়ে — আর সেটা কমিট করুন:
git rm --cached models/sentiment-v1.joblib
git commit -q -m "Stop tracking model files"
ls models
git status --short
git check-ignore -v models/sentiment-v1.joblibrm 'models/sentiment-v1.joblib'
sentiment-v1.joblib
.gitignore:19:models/ models/sentiment-v1.joblibফাইলটা ডিস্কে আছে, Git আর ট্র্যাক করছে না, আর এখন থেকে models/ নিয়ম তাকে বাইরে রাখে। পুরো ফোল্ডারের জন্য git rm -r --cached models/। একটা সতর্কতা: কোনো টিমমেট এই কমিট পুল করলে Git তার কপি মুছে দেবে, কারণ Git-এর চোখে ফাইলটা সরানো হয়েছে। টিমকে জানিয়ে রাখুন, আর মডেল ফাইল রাখুন তাদের জন্য উপযুক্ত জায়গায় (শেয়ার্ড ড্রাইভ, ক্লাউড স্টোরেজ, Git LFS বা DVC — অ্যাডভান্সড টিউটোরিয়ালে আছে)।
আর পুরোনো সংস্করণ হিস্ট্রিতে থেকেই যায়। রিপোজিটরি যে-ই ক্লোন করে, সে চিরকালের জন্য সেটা ডাউনলোড করে:
git log --oneline -- models/sentiment-v1.joblib095aca1 Stop tracking model files
7a92438 Add keyword review analyser, sample reviews and first modelছোট একটা মডেল ফাইলের জন্য এটা শুধু অপচয়। সিক্রেটের জন্য এটা বিপর্যয়।
কমিট হওয়া সিক্রেট মানেই ফাঁস হওয়া সিক্রেট
এই ভুলটা প্রতিটা ডেভেলপার একবার করে। নাদিয়া তাড়ায় আছে; "দ্রুত টেস্ট করতে" কি-টা সরাসরি কোডে বসিয়ে কমিট করে ফেলল:
cat > llm_client.py <<'EOF'
API_KEY = "sk-proj-EXAMPLE-not-a-real-key"
EOF
git add llm_client.py
git commit -q -m "Add LLM client"সে খেয়াল করে, কি-টা এনভায়রনমেন্ট থেকে পড়ার ব্যবস্থা করে, আর সংশোধনটা কমিট করে:
cat > llm_client.py <<'EOF'
import os
API_KEY = os.environ["OPENAI_API_KEY"]
EOF
git commit -q -am "Read the API key from the environment"
cat llm_client.pyimport os
API_KEY = os.environ["OPENAI_API_KEY"]বর্তমান ফাইল পরিষ্কার। কিন্তু কমিট একটা স্ন্যাপশট, আর পুরোনো স্ন্যাপশট এখনো আছে। রিপোজিটরির কপি আছে এমন যে কেউ কখনো কমিট হওয়া প্রতিটা সংস্করণে খুঁজতে পারে (-S সেই কমিটগুলো বের করে যেখানে একটা স্ট্রিং যোগ বা মোছা হয়েছে) এবং পুরোনো ফাইলটা ছাপতে পারে:
git log --oneline -S "sk-proj"
git show HEAD~1:llm_client.pyb396fd5 Read the API key from the environment
d7ccc6d Add LLM client
API_KEY = "sk-proj-EXAMPLE-not-a-real-key"রিপোজিটরিটা কখনো GitHub-এ পুশ হয়ে থাকলে ধরে নিন কি-টা অন্য কারও হাতে: বট কয়েক মিনিটের মধ্যেই পাবলিক রিপোজিটরিতে কি খুঁজে বের করে। করণীয়ের ক্রম:
- আগে কি-টা বাতিল (revoke) বা বদলান (rotate), প্রোভাইডারের ড্যাশবোর্ডে (OpenAI, Anthropic, AWS, আপনার ডেটাবেস)। ক্ষতি আসলে থামায় শুধু এই ধাপটাই। ইউসেজ আর বিলিং পাতায় অচেনা কার্যকলাপ আছে কি না দেখুন।
- তারপর দরকার হলে হিস্ট্রি থেকে সরান। এতে কমিট নতুন করে লিখতে হয় (
git filter-repo), যা অ্যাডভান্সড টিউটোরিয়ালে প্রয়োজনীয় সতর্কতাসহ শেখানো হবে। নাদিয়া যেমন করেছে, নতুন কমিটে লাইনটা মুছে দেওয়া যথেষ্ট নয়। - পরেরটা ঠেকান: প্রথম কমিট থেকেই
.gitignore-এ.env, কি শুধু এনভায়রনমেন্ট ভেরিয়েবলের মাধ্যমে, আর একটা সিক্রেট স্ক্যানার।
এখানে GitHub সাহায্য করে। পাবলিক রিপোজিটরিতে সিক্রেট স্ক্যানিং (secret scanning) আপনাআপনি ও বিনামূল্যে চলে, আর পুশ প্রোটেকশন (push protection), যা পাবলিক রিপোজিটরিতে ডিফল্টভাবে চালু, চেনা কি (OpenAI, Anthropic, AWS, GitHub টোকেন ও আরও অনেক) আছে এমন git push আটকে দেয় এবং কোন কমিট ও লাইনে পেয়েছে তা জানায়। এগুলোকে সিটবেল্ট ভাবুন, অসতর্ক হওয়ার অজুহাত নয়: এরা শুধু চেনা ফরম্যাটের কি-ই চেনে, আর ফ্রি প্ল্যানের প্রাইভেট রিপোজিটরি একই সুরক্ষা পায় না।
ইগনোর নিয়ম রাখার তিনটা জায়গা
| কোথায় | শেয়ার হয়? | কীসের জন্য |
|---|---|---|
রিপোজিটরির ভেতরের .gitignore (সাবফোল্ডারে আরও থাকতে পারে) | হ্যাঁ, কমিট করা | প্রজেক্ট যা বানায় তার সবকিছু: .env, .venv/, ডেটা, মডেল, বিল্ড আউটপুট |
core.excludesFile দিয়ে সেট করা গ্লোবাল ফাইল | না, শুধু আপনার মেশিনে | আপনার এডিটর আর অপারেটিং সিস্টেম: .vscode/, .idea/, .DS_Store, Thumbs.db |
.git/info/exclude | না, শুধু এই একটা রিপোজিটরির জন্য | একটা প্রজেক্টে ব্যক্তিগত খসড়া ফাইল |
গ্লোবাল ফাইলটা একবার সেট করলে প্রতিটা প্রজেক্টে আপনার এডিটরের ফোল্ডার যোগ করার ঝামেলা বাঁচে:
printf '.DS_Store\nThumbs.db\n.idea/\n' > ~/.gitignore_global
git config --global core.excludesFile ~/.gitignore_global
touch .DS_Store
git check-ignore -v .DS_Store/home/nadia/.gitignore_global:1:.DS_Store .DS_Storeপ্রজেক্টের .gitignore-ও শূন্য থেকে বানাতে হয় না। GitHub-এর সংগ্রহ github.com/github/gitignore-এ যত্নে রাখা একটা Python.gitignore আছে, আর রিপোজিটরি বানানোর সময় GitHub সেটা টেমপ্লেট হিসেবে দেয়। সেটা দিয়ে শুরু করুন, তারপর নিজের ডেটা, মডেল আর নোটবুকের নিয়ম যোগ করুন।
আসল AI কাজে এটা কোথায় লাগে
- প্রতিটা LLM অ্যাপে প্রোভাইডারের কি থাকে। টিমগুলো সেগুলো লোকালি
.env-এ, CI-এর জন্য GitHub Actions সিক্রেটে আর প্রোডাকশনে হোস্টিং প্ল্যাটফর্মের সেটিংসে রাখে; রিপোজিটরিতে থাকে শুধু.env.example। - ডেটাসেট আর মডেল ওয়েট থাকে Git-এর বাইরে: অবজেক্ট স্টোরেজ (S3, Google Cloud Storage), Hugging Face Hub, Git LFS বা DVC-তে। রিপোজিটরিতে থাকে কোড, টেস্টের জন্য ছোট একটা নমুনা, আর বাকিটা আনার একটা স্ক্রিপ্ট বা নির্দেশক।
- এক্সপেরিমেন্টের আউটপুট (
runs/,wandb/,mlruns/,outputs/) সাধারণত উপেক্ষিত থাকে; জরুরি ফলাফল বরং এক্সপেরিমেন্ট ট্র্যাকারে লগ করা হয়। - ফাঁস হওয়া কি-র আসল খরচ আছে। বটের পাওয়া একটা কি দিয়ে কয়েক ঘণ্টায় আপনার অ্যাকাউন্টে হাজার হাজার LLM রিকোয়েস্ট চালানো যায়; এ কারণেই প্রোভাইডার আর GitHub এগুলো স্ক্যান করে।
সাধারণ ভুল
- প্রথম
git add .-এর পরে.gitignoreযোগ করা। ফাইলগুলো ততক্ষণে ট্র্যাকড, নিয়মগুলো তাদের উপর কিছুই করে না। সমাধান: প্রথম কমিটের আগেই.gitignoreলিখুন; দেরি হয়ে গেলে ফাইলগুলোতেgit rm --cachedচালিয়ে কমিট করুন। - ফোল্ডার ইগনোর করে তার ভেতরের কিছু ফিরিয়ে আনার চেষ্টা।
data/-এর পরে!data/sample/কিছুই করে না, কারণ Git বাদ দেওয়া ফোল্ডারের ভেতরে তাকায় না। সমাধান:data/*তারপর!data/sample/, আরgit check-ignore -vদিয়ে যাচাই। - নতুন কমিটে সিক্রেট মুছে যায় ভাবা। কি-টা আগের প্রতিটা কমিটে আর প্রতিটা ক্লোনে থেকে যায়। সমাধান: আগে কি বদলান, দরকার হলে তারপর হিস্ট্রি পরিষ্কার করুন।
- "টিমের জন্য"
.envকমিট করা। এখন বা পরে রিড অ্যাক্সেস আছে এমন যে কেউ (একজন কন্ট্রাক্টর, একটা পাবলিক ফর্ক, চুরি যাওয়া ল্যাপটপ) প্রোডাকশনের ক্রেডেনশিয়াল পেয়ে যায়। সমাধান:.env.exampleকমিট করুন, আর আসল মান শেয়ার করুন পাসওয়ার্ড ম্যানেজার বা প্ল্যাটফর্মের সিক্রেট সেটিংসের মাধ্যমে। - বেশি ইগনোর করে ফেলা।
*.json-এর মতো নিয়মpackage.jsonবা অ্যাপের দরকারি কনফিগ ফাইলও লুকিয়ে ফেলে, আর টিমমেটের ক্লোন ভেঙে যায়। সমাধান: সংকীর্ণ নিয়ম লিখুন, আর মাঝে মাঝেgit status --ignoredদেখুন।
নিজে চেষ্টা করুন
এগুলো review-analyser রিপোজিটরিতে, ক্রম মেনে করুন।
- সহজ: আপনার ট্রেনিং স্ক্রিপ্ট রুটে
training.logআরlogs/-এ আরও লগ লেখে।training.logআরlogs/run-01.logবানান, সব.logফাইল ইগনোর করে এমন একটা নিয়ম যোগ করুন, আরgit check-ignore -vদিয়ে প্রমাণ করুন। - মাঝারি: পূর্বাভাস সেভ হয়
outputs/-এ, কিন্তু ফাইলের ফরম্যাট ব্যাখ্যা করাoutputs/README.mdকমিট হওয়া উচিত।outputs/-এর সবকিছু ইগনোর করে শুধু ওই README বাদ রাখে এমন নিয়ম লিখুন,outputs/README.mdআরoutputs/predictions.csvবানান, আরgit status --short --untracked-files=all(যা নতুন ফোল্ডারের ভেতরের ফাইলও দেখায়) দিয়ে দেখান যে শুধু README-ই দেখা যাচ্ছে। - কঠিন: একজন টিমমেট একটা টোকেনসহ
secrets.jsonকমিট করে ফেলেছে। ফাইলটা বানিয়ে কমিট করে সেটা অনুকরণ করুন, তারপর ডিস্ক থেকে না মুছে ট্র্যাকিং বন্ধ করুন, ফাইলটা যেন ইগনোর থাকে তা নিশ্চিত করুন, আর কোন কমিটের স্ন্যাপশটে ওটা আছে তার তালিকা দেখান। টোকেনটার নিজের কী করতে হবে?
উত্তর
# Easy
touch training.log
mkdir -p logs && touch logs/run-01.log
echo '*.log' >> .gitignore
git check-ignore -v training.log logs/run-01.log.gitignore:23:*.log training.log
.gitignore:23:*.log logs/run-01.log# Medium
printf 'outputs/*\n!outputs/README.md\n' >> .gitignore
mkdir -p outputs
echo '# Prediction files: one CSV per run' > outputs/README.md
echo 'id,label' > outputs/predictions.csv
git status --short --untracked-files=all M .gitignore
?? outputs/README.mdশুধু .gitignore (বদলানো) আর outputs/README.md দেখা যাচ্ছে; predictions.csv উপেক্ষিত। নিয়মগুলো যেন শেয়ার হয়, তাই দুটোই কমিট করুন:
git add .gitignore outputs/README.md
git commit -q -m "Ignore logs and prediction outputs"# Hard
echo '{"hf_token": "hf_EXAMPLEnotARealToken"}' > secrets.json
git add secrets.json
git commit -q -m "Add config"
git rm -q --cached secrets.json
echo 'secrets.json' >> .gitignore
git add .gitignore
git commit -q -m "Stop tracking secrets.json"
ls secrets.json
git check-ignore -v secrets.json
git log --oneline --all -- secrets.jsonsecrets.json
.gitignore:26:secrets.json secrets.json
03a9ec9 Stop tracking secrets.json
908189b Add configলগে দেখা যাচ্ছে যে কমিটে ফাইলটা যোগ হয়েছিল আর যে কমিটে ট্র্যাকিং বন্ধ হলো; প্রথমটায় টোকেনটা এখনো আছে। টোকেনটা প্রোভাইডারের সাইটে (এখানে Hugging Face) বাতিল করে নতুন নিতে হবে। পুরোনো কমিট হিস্ট্রি থেকে সরানো তার পরের ধাপ, আর সেটা ঐচ্ছিক পরিষ্কার-পরিচ্ছন্নতা, সমাধান নয়।
সারসংক্ষেপ
.gitignoreআনট্র্যাকড ফাইলের যে প্যাটার্ন Git এড়িয়ে যাবে তার তালিকা; এটা কমিট করা হয়, তাই পুরো টিম শেয়ার করে। শেষে মেলা প্যাটার্ন জেতে, আর!ব্যতিক্রম বানায়।- AI প্রজেক্টে অন্তত
.env,.venv/,__pycache__/,.ipynb_checkpoints/, কাঁচা ডেটা আর মডেল ফাইল ইগনোর করুন;.env.exampleআর একটা ছোট ডেটা নমুনা কমিট করুন। git check-ignore -vবলে কোন নিয়ম মিলেছে;git status --short --ignoredসব উপেক্ষিত জিনিস দেখায়।- যে ফাইল আগেই ট্র্যাকড, নিয়ম তার উপর খাটে না:
git rm --cachedনা মুছে ট্র্যাকিং বন্ধ করে, আর পুরোনো সংস্করণ হিস্ট্রিতে থেকে যায়। - কমিটে ঢোকা সিক্রেট ফাঁস হয়ে গেছে: আগে বদলান, তারপর হিস্ট্রি পরিষ্কার করুন (অ্যাডভান্সড টিউটোরিয়ালে)। GitHub-এর সিক্রেট স্ক্যানিং আর পুশ প্রোটেকশন সুরক্ষার জাল, কোনো পরিকল্পনা নয়।
এরপর: ভুল শোধরানো: restore, reset ও revert। খারাপ এডিট ফেলে দেওয়া, ফাইল আনস্টেজ করা, শেষ কমিট ঠিক করা, আর শেয়ার করার আগে ও পরে নিরাপদে কমিট ফিরিয়ে নেওয়া শিখবেন।