عرض عملي: وضع الحسابات المصرفية تحت Git
في هذا الدرس 11 موضوعات
هذا الدرس متاح حاليًا باللغة الإنجليزية فقط، ولم تُنشر نسخته العربية بعد.
Lesson Overview
This is a hands-on lesson. You will take an existing Java project, the Bank Accounts project you have been growing, and put it under Git from scratch, with a clean history. Along the way you will make one planned mistake on purpose, the most common mistake beginners make with Git, and fix it. Everything from lessons L02 to L06 comes together here, and the steps are the first half of the module lab (BEG-046-LAB1).
Your Bank Accounts folder will look different from the one below: your classes, packages, and IDE will differ. Follow the steps, not the exact file names. Menu names and folder names depend on your IDE and operating system, so commands here are given for a terminal. The demo uses a small version of the project with two classes. All commands were run in a scratch folder with Git 2.44 and JDK 21; your hashes will differ.
Learning Objectives
By the end of this lesson you will be able to:
- Turn an existing project folder into a repository.
- Recognise from
git statuswhengit add .is about to stage files that do not belong. - Undo an accidental staging before the first commit.
- Create a
.gitignorebefore the first commit and confirm it works. - Commit a project in small, meaningful steps with clear messages.
- Review the result with
git log --oneline,git ls-files, andgit status.
Written Explanation
The starting point
Here is the demo project after you compiled it (your IDE may put compiled files elsewhere):
bank-accounts/
src/
Account.java
Main.java
out/ <- compiled .class files
.idea/ <- IDE settingsAccount.java has an owner, a balance, and getters. Main.java creates one account and prints it. Running it gives:
Sara: 100.0A good first commit contains only the files a teammate needs to rebuild the project: the source. The out/ and .idea/ folders are generated by tools and must stay out.
Step 1: Initialise the repository
Open a terminal in the project's top folder and check you are in the right place (pwd, ls or dir; BEG-006):
git init -b main
git status -sInitialized empty Git repository in .../bank-accounts/.git/
?? .idea/
?? out/
?? src/Three untracked folders. Two of them should never be committed.
Step 2: The planned mistake
Without a .gitignore, a beginner types the shortcut:
git add .
git status -sA .idea/misc.xml
A out/Account.class
A out/Main.class
A src/Account.java
A src/Main.javaLook closely: compiled .class files and the IDE folder are now staged. This is exactly the habit lesson L06 warned about. Nothing has been committed yet, so it is easy to undo. This is why you read git status before you commit.
Step 3: Undo the staging
You might expect the usual unstaging command, git restore --staged .. In a repository that has no commits yet, it fails:
fatal: could not resolve HEADgit restore --staged copies the staged files back from HEAD, the latest commit, and there is no commit yet. (The official page says --staged restores from HEAD by default; I found the failing message by running it.) In a repository with at least one commit, git restore --staged . is the right command. Before the first commit, use:
git rm -r --cached .
git status -s?? .idea/
?? out/
?? src/--cached removes the files from the staging area only; your files on disk are untouched (lesson L06). Everything is untracked again.
Step 4: Create .gitignore first
Create a file named .gitignore in the top folder with these lines (use a text editor, or printf in a Bash-style terminal; the right way differs by shell):
*.class
out/
.idea/
.envgit status -s?? .gitignore
?? src/out/ and .idea/ are gone from the list. The .env line costs nothing and protects you later. Adjust for your project: if your IDE writes compiled files to another folder, ignore that folder.
Step 5: Commit in small steps
Resist git add . even now, and name what you stage. First commit: the ignore file and the first class.
git add .gitignore src/Account.java
git commit -m "Add Account class with owner and balance"[main (root-commit) 833d77b] Add Account class with owner and balance
2 files changed, 21 insertions(+)
create mode 100644 .gitignore
create mode 100644 src/Account.javaSecond commit: the program that uses it.
git add src/Main.java
git commit -m "Add Main that creates one account"Now you add deposit and withdraw to Account. Compile and run to be sure it works (javac -d out src/*.java, as in your earlier modules), then review before staging:
git diff --stat src/Account.java | 8 ++++++++
1 file changed, 8 insertions(+)git add src/Account.java
git commit -m "Add deposit and withdraw"Step 6: Check the result
git log --onelineab0fa5e Add deposit and withdraw
2948ea1 Add Main that creates one account
833d77b Add Account class with owner and balancegit ls-files.gitignore
src/Account.java
src/Main.javagit statusOn branch main
nothing to commit, working tree cleanThree commits, each with one purpose; only source and .gitignore tracked; nothing pending. That is the shape your lab history should have, with at least five commits for the full lab.
If a command fails with a message about your name or email, set them as in lesson L02 (git config --global user.name and user.email) and repeat the commit. If your own project already has a few classes, do not commit them all at once: group them by purpose, such as the model classes first and the Main wiring last, so that each commit still compiles on its own. That is easy to check and makes the history far more useful later.
What good looks like (checklist)
| Check | Command |
|---|---|
No .class, out/, .idea/ tracked | git ls-files |
| Every message says what changed | git log --oneline |
| Nothing left uncommitted | git status |
.gitignore is committed | git ls-files shows it |
Examples
Example 1: The simplest safe start (simple)
For a brand-new project with one file:
git init -b main
git add Hello.java
git commit -m "Add Hello program"Naming the file instead of using . is a safe habit until you have a .gitignore.
Example 2: Good and bad histories of the same work (practical)
Bad: one commit, git commit -m "bank", with out/ and .idea/ inside. Good:
ab0fa5e Add deposit and withdraw
2948ea1 Add Main that creates one account
833d77b Add Account class with owner and balanceThe second can be read like a story, and each step can be compared or undone separately. Both contain the same code; only one is useful.
Example 3: A new file arrives later (realistic)
A week later you add Customer.java. Because .gitignore already hides compiled files, git status -s shows just:
?? src/Customer.javaYou stage it by name, commit "Add Customer class with name and email", and the history grows cleanly. A .gitignore is a one-time investment that keeps every later status short and honest.
Backend Insight
Every backend project starts like this: a folder, a first commit, an ignore file. The first commit sets the tone. If it holds build output and IDE settings, every teammate's git status is noisy and their IDE settings overwrite each other. A clean first commit also makes later reviews faster, since reviewers only read source.
The demo's discipline (status before add, naming files, small commits) is what teams call a clean history. When something fails in production, a reviewer, an auditor, or you in six months can read the story. Real projects also carry a README and build files, and you will add those in later modules; the rule remains: commit what a teammate needs to rebuild the project, and nothing generated.
Common Mistakes
Mistake 1: git add . before .gitignore
- Incorrect:
git init,git add .,git commit. - Correct:
git init, create.gitignore,git status, then stage by name or withgit add .once the status looks right.
Mistake 2: Using git restore --staged . before the first commit
It fails with fatal: could not resolve HEAD. Use git rm -r --cached . in a repository without commits.
Mistake 3: Running git init in the wrong folder
If you run it in your home folder or in a folder that holds many projects, Git tries to track everything there. Use pwd first, and run git init only in the project's top folder. If it happened, delete the .git folder in that place (and only that one) and start again.
Mistake 4: Putting everything in one first commit
A single "Initial commit" with everything is hard to review. Split by purpose, as in Step 5.
Exercises
Level A: Foundation
A1. Why is it risky to type git add . in a project that has no .gitignore?
أظهر الحل A1
A1. It stages everything in the folder, including compiled files, IDE settings, and files with secrets, which then enter history.
A2. Which command shows which files are tracked?
أظهر الحل A2
A2. git ls-files.
A3. Where must .gitignore live to apply to the whole project?
أظهر الحل A3
A3. In the repository's top folder (it can also exist in subfolders for local rules).
Level B: Application
B1. Take any small Java project of yours. Put it under Git with a .gitignore and at least three commits. Write the commands you ran in order.
أظهر الحل B1
B1. Example:
git init -b main
# create .gitignore with *.class, out/, .idea/, .env
git add .gitignore src/Account.java
git commit -m "Add Account class"
git add src/Main.java
git commit -m "Add Main that uses Account"
git add src/Account.java
git commit -m "Add deposit and withdraw"B2. You staged files with git add . before creating .gitignore and before the first commit. Write the commands to undo it, and explain why you cannot use git restore --staged ..
أظهر الحل B2
B2. git rm -r --cached . removes everything from the staging area (the files stay on disk). git restore --staged . restores the index from HEAD, and a new repository has no HEAD yet, so it fails with fatal: could not resolve HEAD.
B3. Suggest three commit messages for adding an Account class, a Customer class, and a bug fix for a negative balance.
أظهر الحل B3
B3. For example: Add Account class with owner and balance; Add Customer class with name and email; Fix negative balance after withdraw.
Level C: Challenge
C1. In the middle of the project you realise you committed out/Main.class in your second commit. Write the commands that stop tracking it and prevent it from returning. What remains in the second commit?
أظهر الحل C1
C1.
git rm --cached out/Main.class
# make sure .gitignore contains out/ or *.class
git add .gitignore
git commit -m "Stop tracking compiled output"The second commit still contains the file; only later commits stop tracking it.
C2. A teammate's first commit is called "initial" and contains src/, out/, .idea/, and .env. Write a short review comment listing what to change, in order of importance.
أظهر الحل C2
C2. First: remove .env from tracking and treat any password in it as leaked (change it). Then: remove out/ and .idea/ from tracking and add them to .gitignore. Then: split the history into commits that each have a purpose, and replace "initial" with messages that say what was added.
Mini Challenge
Put your own Bank Accounts project under Git, following the steps. Aim for at least four commits that tell a story, a committed .gitignore, and an empty git status at the end. Include the planned mistake: run git add . first, read git status, undo it, and write the ignore file. Save the output of git log --oneline and git ls-files in a text file.
Check your work: no .class files or IDE folders in git ls-files; each message begins with a verb; nothing is left uncommitted.
Summary & Next Lesson
Key takeaways
- Create
.gitignorebefore the firstgit add ., then checkgit status. - Before the first commit, undo staging with
git rm -r --cached .;git restore --staged .needs a commit to restore from. - Stage by name when unsure; commit in small, labelled steps.
- Review with
git log --oneline,git ls-files, andgit status.
Next lesson
Next is "Demo: creating and resolving a merge conflict", where you create a conflict in this same project on purpose and resolve it.
Self-check
- Why does
git restore --staged .fail in a new repository? - What does
git rm -r --cached .do to your files on disk? - What should exist before your first
git add .? - Which command lists the tracked files?
- What is a sign of a clean first history?
أظهر الإجابات
- There is no
HEADcommit yet to restore from. - Nothing; it only removes them from the staging area.
- A
.gitignorethat excludes build output, IDE folders, and secrets. git ls-files.- Small commits with clear messages, only source files tracked, and a clean
git status.
References
- Git documentation,
git restore. It supports that--stagedrestores only the index, and that the source defaults toHEAD. It does not mention the no-commit case; thefatal: could not resolve HEADfailure was observed by running Git 2.44. - Pro Git book, "Recording Changes to the Repository". It supports
git rm --cachedkeeping the file on disk and the role of.gitignore. - Git documentation,
git init. It supportsgit init -bfor the initial branch name. - The demo project, commands, and outputs were run in a scratch folder with Git 2.44 and JDK 21 (javac 21.0.10).
التطبيق
طبّق هذا الدرس بمختبر الوحدة وتمارينها واختبارها.
تعليم الدرس كمكتمل اختياري ويمكنك التراجع عنه في أي وقت. يبقى تقدمك محفوظًا في هذا المتصفح.