4.3 Adding and Managing Files
Key Takeaways
- The GitHub web UI can create text files or upload up to 100 files at 25 MiB each; Git warns at 50 MiB and blocks files larger than 100 MiB in regular Git unless you use Git LFS.
- The local loop is git add to stage, git commit to record a snapshot, and git push to update the GitHub remote; never add secrets.
- Press . on a repository or pull request to open github.dev, a free browser editor that does not clone the repo or provide a terminal.
- Adding a path to .gitignore does not untrack a file that is already committed; use git rm --cached FILENAME and commit the removal.
- Git LFS stores a pointer in Git and the large blob elsewhere; it cannot be used with GitHub Pages or template repositories.
Why GH-900 tests adding files
The third Domain 2 skill is explain how to add and manage files within a repository. After you can name community files and create the repo, the exam asks how bits actually land in Git history. GH-900 is a foundations exam, so you need the GitHub surfaces and the three Git verbs—not a systems-programming tour of the index.
You need write access (or a fork plus pull request) to change files. If you try to create a file in a repository you cannot write, GitHub forks it to your personal account and helps you send a pull request. If the branch is protected, you cannot edit or upload files on that branch in the GitHub web UI; move the work to a new branch (web “create a new branch for this commit,” GitHub Desktop, or CLI) and open a pull request.
Four ways files get into GitHub
Web editor (Create new file)
On the repository home, Add file → Create new file, or the + in the file tree. Type a path; / creates directories. Preview Markdown, then Commit changes. You can commit to the current branch or to a new branch plus pull request—the right choice when you are on the default branch of a shared repo. Filenames created in the web UI may contain only alphanumeric characters and hyphens. Other characters (spaces, most punctuation) require creating the file locally and pushing. Never commit passwords or API keys; GitHub documents git add / commit / push of secrets as a hard warning, and push protection can block a web upload that contains a supported secret.
Web uploads ignore .gitattributes. If you rely on that file for line-ending conversion or similar, use Git on a clone, not the browser drop target.
Upload files
Add file → Upload files, or drag and drop onto the repository page. You can upload up to 100 files in one shot. Browser uploads are capped at 25 MiB per file. After you choose files, you still write a commit message and pick current branch versus new branch. This is the path for images, PDFs, and other binaries that are still under 25 MiB.
Git add, commit, push
Clone (or git init and add a remote), place the file in the working tree, then:
git add— copy the change into the index (staging area).git add .stages everything not ignored; you can add a single path instead.git commit -m "…"— record a snapshot on the current branch in your local repository.git push origin BRANCH— send new commits to GitHub.
Command-line adds can be larger than the browser cap: GitHub warns at 50 MiB and blocks files larger than 100 MiB in ordinary Git. Beyond that you need Git Large File Storage (or a Release asset). Recommended repository size is under 1 GB, and staying under 5 GB is strongly recommended. Git is not a backup product or a database dump store.
github.dev (press .)
While you are signed in and viewing a repository or pull request, press . to open github.dev in the same tab, or > for a new tab. You can also change github.com to github.dev in the URL, or pick github.dev from a file’s edit dropdown. github.dev is a free, browser-sandboxed VS Code–like editor. It does not clone the repository onto a VM; the GitHub Repositories extension fetches files, and unsaved work lives in browser local storage until you commit. There is no terminal and no compute—you cannot build or run the project there. Commit from the Source Control view (Commit & Push). Domain 4 compares github.dev with Codespaces in depth; for Domain 2, remember: . opens a lightweight editor for files, not a full cloud machine.
| Path | Best for | Size / limits | Needs a local clone? |
|---|---|---|---|
| Create new file (web) | Small text and Markdown | Alphanumeric and hyphen names; protected branches blocked | No |
| Upload files (web) | Existing files, images | 25 MiB each, 100 files; push protection may block secrets | No |
git add / commit / push | Daily development, odd filenames, .gitattributes | Warn 50 MiB, block >100 MiB | Yes |
github.dev (. key) | Quick edits in a VS Code layout | Same GitHub file limits; no terminal | No |
| Git LFS | Assets above the Git file cap | Plan caps 2 GB (Free/Pro), 4 GB (Team), 5 GB (Enterprise Cloud) | Yes, with LFS installed |
Moving, renaming, and large files
On GitHub, open the file, click the pencil, and edit the filename field. Type folder/ to move the file into a new or existing subdirectory. Type ../ or Backspace at the start of the path to climb to a parent directory. You can rename in the same commit. Images and some other binaries cannot be moved in the web editor; use the command line. Locally, move the file in the filesystem, then git add . (or git mv). Git records a rename when the index shows a delete plus an add of the same blob. git push publishes it.
Git LFS stores a pointer in Git and the real bytes elsewhere. The pointer records an LFS spec version, a SHA-256 oid, and the size. GitHub fetches the large file using that pointer when you clone. Use LFS when a file must live in the repository but exceeds the 100 MiB Git block (or when you want to avoid the 50 MiB warning). Two hard product limits: Git LFS cannot be used with GitHub Pages and cannot be used with template repositories. If you only need to distribute a build artifact, attach it to a Release instead of tracking it in Git. Each Release asset must still sit under the LFS per-file cap for your plan (2 GB on Free/Pro, 4 GB on Team, 5 GB on Enterprise Cloud).
The already-tracked .gitignore trap
.gitignore tells Git which untracked paths to skip. If secrets.env or node_modules/ was already committed, adding it to .gitignore changes nothing: Git keeps tracking it. Untrack it while leaving the file on disk:
git rm --cached FILENAME
git commit -m "Stop tracking FILENAME"
After that commit, the ignore rule applies. git rm --cached is also the first step GitHub documents when you accidentally committed a huge file in the latest unpushed commit (then amend). Once a secret or a giant blob is in history that you already pushed, ignoring it is not enough—you need history rewriting (git filter-repo or similar), which is beyond GH-900’s depth. The exam bar is: ignore file ≠ untrack; git rm --cached untracks.
Three ignore scopes exist. A committed .gitignore is shared with every clone. ~/.config/git/ignore (Git’s global ignore) applies to every repository on that machine. .git/info/exclude is local to one clone and is never pushed. GH-900 cares most about the committed .gitignore and the cached-file trap.
Exam scenarios and traps
- 25 / 50 / 100 MiB are three different numbers. Browser 25 MiB. Git warning 50 MiB. Git block 100 MiB. LFS after that.
.opens github.dev, not Codespaces. No terminal, no VM, free, must be signed in. Ad blockers and incognito windows are common reasons it fails to load.- Protected default branch plus “edit on GitHub” is a trick question: the UI refuses; create a branch.
- Web-created names cannot contain spaces or most punctuation; the CLI can.
.gitignoreafter the fact does not delete a tracked file from Git.git rm --cacheddoes (from Git, not from disk).- LFS in a template or on GitHub Pages is unsupported. Pick Releases or ordinary files instead.
- Uploading through the website skips
.gitattributes. Line-ending rules need a real Git client. - One hundred files is the web upload batch limit, not a Git object limit.
GH-900 stories sound like: a designer who cannot upload a 40 MiB video in the browser; a developer who added dist/ to .gitignore and still sees it in the pull request; a student who pressed . and wondered why npm test has no terminal; a maintainer who tried to mark an LFS-heavy repo as a template. Pair each story with the limit, the command, or the editor that actually applies.
A contributor committed build/output.bin last week. They added build/ to .gitignore, but the file still appears in git status as a tracked modification. What should they do?
Which size limits apply when you add files to a GitHub repository without Git LFS?
A signed-in user is browsing a repository on github.com and wants a free in-browser VS Code layout to edit files without creating a codespace. What should they do?