Step 87. GitHub Remote Repositories and Your Portfolio — Both Backup and Showcase
Level 1 — Programming and the Inside of a Computer | Difficulty ★★☆☆☆ | Estimated time: 3 hours
Prerequisites: Git basics from Step 86 (init/add/commit/log/checkout).
- What you need: a computer with Git installed. A GitHub account helps, but today’s push/pull exercises can all be followed without an account, using a local simulation.
- Caution: one rule matters most — never upload passwords, API keys, or tokens to a public repository. Today we prove why, with an experiment.
The time machine you made yesterday lives only inside your computer. But computers break, and laptops get lost. The time machine itself needs a backup. And one more thing — in the security industry, the demand "prove your skills" is often settled by a single GitHub profile line rather than a one-page résumé. Today we get the technique of connecting a local repository to a remote one into our hands, and draw the blueprint of your first portfolio repository.
1. Learning Objectives
By the end of this chapter, you will be able to:
- Explain the relationship between local and remote repositories, and the directions of push and pull
- Actually use
git remote add,git push -u,git pull, andgit clone - Explain why tokens (PAT) are used instead of passwords, from the perspectives of permissions, expiry, and revocation
- Exclude files from tracking with
.gitignore - Prove with
git showthat "a deleted file remains in past commits," and state the correct response when a secret leaks
2. Background Knowledge — Today’s Tools and Concepts
Today’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | Git Bash (Windows) + the GitHub website (Screen examples) |
| Today’s commands | git init --bare, git remote add/-v, git push -u, git pull, git clone, git show hash:file |
| Concepts needed | Local/remote repositories, push and pull, PAT (personal access token), .gitignore, README |
| Today’s artifacts | A repository remote-lab synced with a remote, and a portfolio design |
2-1. Local and Remote — Two Repositories
What you made in Step 86 is a local repository. What you make on GitHub is a remote repository. The two are a cloned pair sharing the same history, and you synchronize them with commands.
- push — push new local commits up to the remote
- pull — pull new remote commits down to the local
Even working across two machines — a home computer and a laptop — putting the remote in the middle and pushing/pulling keeps both sides always in the same state. Solo, it’s a backup; in collaboration, this channel becomes the team’s artery.
2-2. README — The Repository’s Front Gate
Open a repository on GitHub and the first thing you see is README.md. It’s an introduction document describing "what this repository is and how to run it" (Markdown — the format you learned in Step 47).
In the security industry, a README carries unusual weight. If the maker of a tool can’t even write its explanation, no one will trust and use that tool. If code is skill, the README is the translation of that skill.
2-3. Public and Secrets — The Robots Arrive in Seconds
GitHub repositories are chosen as public or private. Public means anyone can see them — bots included. All over the world there are automated bots scanning newly uploaded code in public repositories in real time, and their target is secrets uploaded by mistake — passwords, API keys, tokens.
Within seconds to minutes of a key going up, it gets stolen, and if it’s a cloud key, incidents where a cryptocurrency mining server is set up immediately genuinely repeat. Worse, even if you delete the file and commit again, the secret remains as-is in the past commit. We prove it ourselves in 3-6.
Today’s ironclad rule: before committing, ask "is there no secret in this file?" Settings that need secrets go not in code but in a separate file, and that file stays outside Git via .gitignore.
2-4. .gitignore — The List That Tells Git What to Ignore
.gitignore is a list meaning "don’t track files and folders whose names are written here." Representative entries:
venv/ # Python virtual environment — thousands of installed files, no need to upload
__pycache__/ # cache Python generates automatically
*.log # log files — a secret might get stamped in by mistake
.env # a settings file collecting passwords and keys
3. Follow Along
Today’s exercises proceed along two branches. If you have a GitHub account, upload to real GitHub; if you don’t (or don’t want to upload anything externally), you can practice push/pull identically by setting up a local bare repository pretending to be the remote. Every measurement in this chapter was verified with this local-simulation approach — the commands and outputs are identical when using GitHub.
3-1. Signing Up for GitHub and Creating Your First Repository (Screen example)
Input:
- Go to github.com, sign up, and complete email verification
- Click the
+at the top right → New repository - Enter
security-studyas the Repository name, select Public, leave "Add a README file" unchecked, and click Create repository
Output example (GitHub screen — guidance, not a measurement): an empty repository screen opens, showing the guidance "…or push an existing repository from the command line" with three lines of commands.
How to read it: GitHub is already telling you the next commands to type. We’re the side that already has a local repository (=existing repository). Since the repository name is your portfolio’s title, pick a name that reveals "what it holds," like security-study.
3-2. Making a Practice Remote — git init –bare
This is the branch for practicing without GitHub. A bare repository is a pure remote-use repository with no working directory — only the history warehouse (the contents of .git).
Input:
git init --bare security-study.git
mkdir remote-lab && cd remote-lab && git init
echo "# security-study" > README.md
git add README.md && git commit -m "first commit: README"
Output (measured 2026-09-09, path altered):
Initialized empty Git repository in C:/Users/yourname/.../security-study.git/
[main (root-commit) c64a247] first commit: README
1 file changed, 1 insertion(+)
How to read it: security-study.git plays the role of the GitHub repository, and remote-lab plays the role of my local repository. If you’re using GitHub, the repository you made in 3-1 takes the bare repository’s place.
3-3. Connecting and the First push — git remote add
Input (local simulation):
git remote add origin ../security-study.git
git push -u origin main
git remote -v
If you’re using GitHub, only the address on the first line differs — https://github.com/yourid/security-study.git.
Output (measured 2026-09-09):
branch 'main' set up to track 'origin/main'.
To ../security-study.git
* [new branch] main -> main
origin ../security-study.git (fetch)
origin ../security-study.git (push)
How to read it: origin is the conventional nickname for "my default remote repository." [new branch] main -> main means "the local main went up to the remote," and thanks to the -u option, Git now knows where to upload even if you just type git push. You can check the registered address anytime with remote -v.
3-4. The Token Wall — GitHub Authentication (Screen example)
The first time you push to GitHub, it asks for an ID and password. Here’s an important wall — GitHub has abolished password authentication.
Output example (when GitHub authentication fails — a message that doesn’t appear in the local simulation):
remote: Password authentication is not supported for Git operations.
How to read it: instead of a password, you must issue a PAT (Personal Access Token) — a "conditional key" — and place it in the password field.
Issuance procedure (GitHub screen): top-right profile → Settings → Developer settings at the very bottom → Personal access tokens → Tokens (classic) → Generate new token. Set the name to something like my-laptop, check the repo permission, set a period of about 90 days, and generate. Keep the token string — shown only once — somewhere safe like a password manager. When push asks for a password, paste this token (it’s normal for nothing to appear on screen as you paste).
Why a token is safer: a token has narrower permissions than a password (like repo only) and an expiration date, and if a leak is suspected it can be revoked (Revoke) immediately. It’s safe because it’s a key you can throw away. And the token itself is also a secret — never write it in code or upload it to a public repository.
3-5. pull — Simulating a Second Computer
The remote’s true power shows when you "continue work from somewhere else." Let’s imitate a second computer with a folder.
Input:
cd ..
git clone security-study.git second-pc
cd second-pc
echo "print('net map')" > netmap.py
git add netmap.py && git commit -m "second PC: add netmap"
git push
cd ../remote-lab
git pull
ls
Output (measured 2026-09-09, clone’s path output altered):
Cloning into 'second-pc'...
done.
From ../security-study
4c54a57..e5b9825 main -> origin/main
Updating 4c54a57..e5b9825
Fast-forward
netmap.py | 1 +
The ls result shows netmap.py newly arrived.
How to read it: clone is a command that copies an entire remote repository to make a new local repository. When the commit the second PC pushed was pulled into the first folder with pull, the file appeared. Fast-forward means "the histories didn’t diverge, so it just slid forward as-is."
3-6. Make a Prediction — Is the Deleted Key Still Alive?
You wrote a fake API key into config.py and committed it, then deleted that line and committed again. Can an attacker recover this key?
- (a) It’s deleted, so impossible
- (b) Open the past commit and it’s there as-is
- (c) You didn’t push, so it’s safe
Check for yourself:
echo 'API_KEY = "FAKE_KEY_FOR_TEST"' > config.py
git add config.py && git commit -m "add config"
sed -i 's/FAKE_KEY_FOR_TEST//' config.py # on Windows, deleting that line in Notepad works too
git add config.py && git commit -m "remove key"
git log --oneline
git show HEAD~1:config.py
Output (measured 2026-09-09):
262eaa8 remove key
344e969 add config
c64a247 first commit: README
API_KEY = "FAKE_KEY_FOR_TEST"
The answer is (b). git show HEAD~1:config.py ("show me this file as of one commit back") shows the deleted line as-is. Delete the file and history remains. That’s why, when you’ve committed and pushed a secret, the correct answer isn’t "delete it" — it’s "revoke that key immediately and issue a new one."
Why it matters: this experiment is a complete proof of why the ironclad rule in 2-3 exists. You’ve become someone who "verified" this warning, not someone who "heard" it.
3-7. .gitignore — Confirming with Your Eyes That It’s Ignored
Input:
printf "venv/\n__pycache__/\n*.log\n.env\n" > .gitignore
mkdir venv && echo "x" > venv/junk.py
echo "SECRET=abc" > .env
git status
Output (measured 2026-09-09):
On branch main
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
nothing added to commit but untracked files present (use "git add" to track)
How to read it: even though you created venv/ and .env, they don’t appear in the status list — .gitignore took effect immediately. ("Your branch is ahead … by 2 commits" is a notice that "there are 2 local commits not yet pushed.") Next, record the list itself too with git add .gitignore && git commit -m "add gitignore" && git push.
3-8. Make a Prediction — If Both Sides Commit Separately, Does push Work?
The second PC has already pushed. The first folder, unaware of that (without pulling), commits and pushes — what happens?
- (a) It goes up as-is
- (b) The remote contents get overwritten
- (c) Git refuses
Check for yourself (measured 2026-09-09):
To ../security-study.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to '../security-study.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. ...
hint: 'git pull' before pushing again.
The answer is (c). If the remote has commits you don’t know about, Git refuses to overwrite. But the latest Git, even when you type git pull here, doesn’t merge right away — it asks which method (measured 2026-09-09):
fatal: Need to specify how to reconcile divergent branches.
Fix: pull with the merge method, then push again.
git pull --no-rebase
git push
If the two folders edited the same part of the same file, a conflict occurs at this moment — in the measurement, CONFLICT (content): Merge conflict in README.md actually appeared. The true nature of conflicts and how to resolve them is covered head-on in the next chapter.
3-9. Organizing the README and Portfolio
Input: write the README.md at the repository root with a skeleton like this.
# security-study
A study-log repository for learning the basics of information security.
## Folder guide
- `python-basic/` — Python syntax practice code
- `network-tools/` — my own port scanner and network observation tools
## Progress
Currently in Level 1 — Programming and the Inside of a Computer.
How to read it: a visitor must be able to tell within 5 seconds "what this person studies and how far they’ve come." A portfolio is evaluated not by "did a lot" but by "it’s organized" — move the practice files from Steps 41–46 into python-basic/, and the port scanner and network exercises into network-tools/, building a structure that reads well to others.
4. Missions & Exercises
Mission — A Synchronized Repository and a Portfolio Design
- Following the flow of 3-2~3-3, connect a local repository to a remote (GitHub or local bare) and push
- From a cloned "second computer" as in 3-5, commit and push, then pull from the original repository and confirm the file arrives
- Put
venv/,__pycache__/,.envinto.gitignoreand confirm those files don’t appear ingit status - Design a portfolio folder structure (2 or more folders) and a README draft in your notes
- (If you have a GitHub account) create a real repository, push, and open the address in a private window (logged out) to check "how it looks to others"
Exercises
Exercise 1. Explain the directions of push and pull using the words "local/remote," and state in order the procedure by which two computers share the same repository.
Exercise 2. Explain why GitHub abolished password authentication and requires a PAT, using the token’s three characteristics (permissions, expiry, revocation).
Exercise 3. You committed a file containing a password, deleted it, recommitted, and pushed. Why is this still a dangerous state, and what’s the correct response?
Exercise 4. Explain the situation in which git push is rejected with ! [rejected] main -> main (fetch first), and the procedure to resolve it.
5. Model Answers & Completion Criteria
Mission Model Answer
The whole flow follows exactly the measured order of section 3. Collecting just the key verification commands:
git remote -v # is the origin address registered?
git push # does it go up without rejected?
git log --oneline # do local and remote commits match?
git status # are venv/ and .env absent from the list?
For pull verification, commit and push from a cloned folder as in 3-5, then git pull in the original folder — success is when the new file shows in ls. The README draft passes if it contains ① a one-line repository introduction ② a folder guide ③ current progress.
How to verify: ① does remote -v show origin? ② do the two folders (or two computers) show the same log --oneline? ③ does .env stay out of status even after you create it? All "yes" means complete.
Exercise Answers
Answer 1. Push is pushing new local commits up to the remote; pull is pulling new remote commits down to the local. Procedure for two machines sharing: on one side, create the remote and connect (remote add), then push → on the other side, clone → afterward each works and pushes, and before starting, sync with pull.
Answer 2. A password is a master key opening every permission of the account, but a token is ① a narrow key holding only needed permissions like repo, ② has an expiration date so it’s not valid forever, and ③ if leaked, only that token needs to be revoked. It’s safe because it’s a key you can throw away.
Answer 3. Because even after deleting and recommitting, the secret remains as-is in the past commit (measured in 3-6), and once pushed, anyone can extract it with git show. If the repository is public, bots may have already collected it. The correct response isn’t tidying the file — it’s immediately revoking that password/key and issuing a new one.
Answer 4. It’s the situation where the remote has commits the local doesn’t (a case where another computer or the web pushed first). Fix: first merge the remote changes with git pull --no-rebase (if a conflict occurs, resolve it with the next chapter’s method), then git push. Since the latest Git may show fatal: Need to specify how to reconcile divergent branches. asking for a method, specify --no-rebase explicitly (measured in 3-8).
Completion Criteria Checklist
- [ ] I can connect a local repository to a remote (remote add) and push
- [ ] I can receive a "second computer’s" changes with clone and pull
- [ ] I can explain why a PAT is safer than a password
- [ ] I can exclude files from tracking with
.gitignore - [ ] I can prove with
git showthat "a deleted file remains in past commits" - [ ] I can explain that the response to a secret leak is "revoke the key and reissue"
- [ ] Mission: I completed the synchronization verification and portfolio design
6. Common Pitfalls & Fixes
Wall 1. My password gets rejected on push
Symptom (Screen example — when connecting to GitHub):
remote: Password authentication is not supported for Git operations.
Cause: GitHub has abolished password authentication. It only accepts PATs.
Fix: issue a token following the procedure in 3-4 and use it in the password field. On Windows, an old password may be stored in Credential Manager and keep failing — delete the git:https://github.com entry under Control Panel → Credential Manager → Windows Credentials and try again.
Wall 2. A "remote origin already exists" error occurs
Symptom (measured 2026-09-09):
error: remote origin already exists.
Cause: origin is already registered (you connected once in the past).
Fix: check the current address with git remote -v, and to change it, use git remote set-url origin newaddress.
Wall 3. push is blocked with "rejected (fetch first)"
Symptom (measured 2026-09-09):
! [rejected] main -> main (fetch first)
error: failed to push some refs to '../security-study.git'
Cause: the remote has commits the local doesn’t (such as when another computer pushed first).
Fix: first bring the remote changes with git pull --no-rebase, then push again. Since the latest Git asks for a method on pull with fatal: Need to specify how to reconcile divergent branches., specify --no-rebase (merge). If a conflict occurs while merging, we learn the solution in the next chapter.
Wall 4. Thousands of files from the venv folder got uploaded
Symptom: push takes forever, and the repository is full of library files.
Cause: you added before creating .gitignore. Ignore applies only to "files not yet tracked."
Fix: untrack only with git rm -r --cached venv (the files themselves stay on your computer), check .gitignore, then commit and push.
Wall 5. I wrote a token in code and uploaded it
Symptom: you belatedly discover you hardcoded a token in a settings file and pushed it.
Cause: you forgot 3-6’s "history remains." Delete it and it still stays in past commits.
Fix: tidying the file isn’t enough. Immediately revoke (Revoke) that token on GitHub’s token page and issue a new one. From now on, keep tokens in a separate file like .env and register that file in .gitignore.
7. Summary
Today’s Concepts
| Concept | One-line explanation |
|---|---|
| Local/remote repository | The repository on my computer and its online replica — a pair sharing the same history |
| push / pull | Pushing local→remote / pulling remote→local |
| clone | Copy an entire remote repository to make a new local repository |
| Bare repository | A pure remote-use repository with history only, no working folder — today’s practice partner |
| PAT | A conditional key with narrow permissions, an expiration date, and revocability |
| .gitignore | A list saying "don’t track this file" — applies only to files not yet tracked |
| README | The repository’s front gate. It must read within 5 seconds |
Today’s Commands
| Command | What it does |
|---|---|
git init --bare name.git |
Make a practice remote (bare) repository |
git remote add origin address |
Register the remote repository in the address book |
git remote -v |
Check the registered remote address |
git push -u origin main |
First push + set the default destination |
git pull --no-rebase |
Pull remote changes with the merge method |
git clone address folder |
Copy a remote to make a new local repository |
git show hash:file |
Extract a file’s contents from a past commit |
git rm -r --cached folder |
Untrack only (files remain) |
An Instinct More Important Than Commands
The moment code goes up on a public repository, it’s seen by people and bots all over the world. Remember 3-6’s experiment — "even deleted lines remain in history." One breath asking "is there no secret in this file?" before committing is what separates a portfolio from an incident report. And a push being rejected or a pull asking for a method isn’t a malfunction — it’s a notice that "the remote has changes you don’t know about" — don’t panic; pull, then push again.
Once every box is checked, Step 87 is complete. Click the checkbox in the sidebar to save your progress.