What this quiz covers
This quiz focuses on Using Gitignore, giving you a quick way to practice the rules, question types, and explanations that matter most for R Programming.
A repository's committed .gitignore contains /.Rproj.user/. A teammate nevertheless runs git add -f .Rproj.user/settings/session.json and commits that file. Another developer then clones the repository and changes the committed session file.
What should the second developer expect?
.gitignore rule.git add -f is used again.R Programming Quiz
Practice Using Gitignore in R Programming with focused quiz questions that help you check what you know, review explanations, and build confidence with test-style prompts.
This quiz focuses on Using Gitignore, giving you a quick way to practice the rules, question types, and explanations that matter most for R Programming.
Try each quiz question before looking at the correct answer. Use the explanations to review missed ideas, then come back to similar questions until the pattern feels familiar.
A repository's committed .gitignore contains /.Rproj.user/. A teammate nevertheless runs git add -f .Rproj.user/settings/session.json and commits that file. Another developer then clones the repository and changes the committed session file.
What should the second developer expect?
.gitignore rule.git add -f is used again..gitignore, the most important concept to internalize is that tracking status overrides ignore rules. A .gitignore file only prevents untracked files from being staged — it has no power over files already in the repository's commit history.
Here's what happened in this scenario: the first developer used git add -f (the force flag) to explicitly bypass the .gitignore rule and commit session.json. The moment that file entered the commit history, Git began tracking it. From that point forward, the .gitignore entry for /.Rproj.user/ becomes irrelevant to this file — Git will dutifully clone it, diff it, and stage changes to it like any other tracked file. So D is correct: the second developer receives the file during cloning, and any modifications they make will be visible to Git as normal changes.
A describes a behavior that simply doesn't exist. Git never strips committed files from a clone based on ignore rules — cloning is a faithful reproduction of the repository's tracked content. B is also false; Git does not reject commits or clones because a tracked path happens to match a .gitignore pattern. The force-add workflow is valid and common, even if inadvisable. C is the trickiest distractor — it implies the file is somehow "half-tracked," requiring git add -f for future changes. This misunderstands what force-add does: it's only needed to initially stage an ignored file, not to stage subsequent changes once it's tracked.
A useful rule of thumb: "once tracked, always tracked (until explicitly removed)." If you want to stop tracking a file that's already committed, you need git rm --cached, not a .gitignore entry.A developer expects the untracked file analysis/.RData to be ignored, but several repository-level, nested, and global ignore rules are in effect. The developer wants to identify the exact matching pattern and the file in which that pattern is defined, without changing the index.
Which command is most directly suited to this diagnosis?
git status --ignored to list ignored paths in the working treegit diff --cached analysis/.RDatagit ls-files --stage analysis/.RDatagit check-ignore -v analysis/.RData (correct answer).gitignore files and global rules are layered on top of each other — you need a command that actively traces the ignore logic and reports back the winning rule and its source file. That's the core concept being tested here.
git check-ignore -v is precisely that tool. The -v (verbose) flag tells Git not just whether a file is ignored, but which pattern matched and which file that pattern lives in. The output format is <source>:<linenum>:<pattern> <pathname>, giving you everything you need to pinpoint the exact rule — no index changes, no side effects. That makes D the correct answer.
A is tempting but incomplete. git status --ignored will list ignored files in the working tree, but it doesn't tell you which pattern or which .gitignore file is responsible. It's useful for discovery, not diagnosis.
B is a red herring. git diff --cached compares staged (indexed) content against the last commit. An untracked, ignored file never enters the index, so this command produces no meaningful output for the scenario described.
C is similarly off-track. git ls-files --stage shows staged file metadata from the index. Again, since the file is untracked and ignored, it won't appear in the index at all, making this command irrelevant.
A useful memory anchor: think of check-ignore -v as a "blame" command for ignore rules — just as git blame traces who wrote a line of code, check-ignore -v traces which rule silenced your file.An R project contains forecast.Rproj, .Rproj.user/, renv.lock, and renv/library/. The team wants clones to retain the project descriptor and reproducible dependency lockfile, but not RStudio's per-user state or the machine-specific installed package library.
Which pair of .gitignore entries best matches the team's intent?
/*.Rproj
/renv.lock/.Rproj.user/
/renv/library/ (correct answer)/.Rproj.user/
/renv/*.Rproj
renv/libraryforecast.Rproj (the project descriptor) and renv.lock (the dependency lockfile), and ignore .Rproj.user/ (RStudio's per-user state) and renv/library/ (the machine-installed packages). Option B does exactly this: /.Rproj.user/ ignores only the per-user RStudio directory, and /renv/library/ ignores only the installed package cache — leaving renv.lock intact so teammates can run renv::restore() to reproduce the environment.
Option A gets things backwards — it ignores the .Rproj file itself (which the team wants to keep) and the renv.lock lockfile (also wanted), which defeats the entire reproducibility goal. Option C ignores the entire /renv/ directory, which would also eliminate renv.lock along with the library — overkill that breaks reproducibility for clones. Option D uses *.Rproj without a leading slash, which would match any .Rproj file anywhere in the project tree, and renv/library lacks a trailing slash, meaning it could fail to correctly match the directory in all Git implementations.
A useful rule of thumb: in .gitignore, a leading slash anchors the pattern to the repository root, and a trailing slash explicitly marks a directory. When you see questions about R project hygiene, always ask yourself — am I ignoring the lockfile or just the library? The lockfile is the blueprint; the library is the build output.A generated output/ directory contains many disposable files and one shareable file, output/README.md. The current rules are:
output/
!output/README.md
Git still treats README.md as ignored because the parent directory itself is excluded.
Which replacement rules allow output/README.md to be tracked while ignoring the other contents of output/?
output/*
!output/README.md (correct answer)output/
!output/README.md!output/README.md
output/*output/*.md
!output/README.md.gitignore, you need to understand a critical rule: Git cannot un-ignore a file inside a completely ignored directory. Once a directory pattern like output/ is listed, Git stops descending into it entirely, making any subsequent negation rules for files inside it ineffective.
The fix is to ignore the directory's contents rather than the directory itself. Using output/* tells Git to ignore everything within output/, but it still traverses the directory. That means the follow-up rule !output/README.md can successfully re-include that specific file. This is exactly what A does — output/* ignores all contents, then !output/README.md rescues the one file you want tracked. This is the correct approach.
B is the original broken pattern from the passage. output/ excludes the entire directory as a unit, so Git never inspects its contents and the negation rule has no effect.
C reverses the order of A's rules. In .gitignore, rules are processed top-to-bottom, with later rules overriding earlier ones. Placing !output/README.md first and output/* second means the ignore rule wins, silencing the negation.
D uses output/*.md to ignore all Markdown files in the directory, then tries to un-ignore README.md. Even if the directory traversal issue were resolved, this would still fail because README.md matches *.md and the negation of a match within the same pattern scope doesn't work as intended here — and it also fails to ignore non-.md files correctly.
Remember the key rule: use a glob (dir/*) to ignore contents, not a trailing slash (dir/), whenever you need negation exceptions inside a directory.A repository already contains a committed .Rproj.user directory. A developer then adds /.Rproj.user/ to the repository's .gitignore, but git status continues to show modifications to files inside that directory. The developer wants to keep the local directory while stopping Git from tracking it.
Which action should the developer take?
git rm -r --cached .Rproj.user, commit the removal and .gitignore change, and retain the working-tree directory. (correct answer)git rm -r .Rproj.user, commit the deletion and .gitignore change, and recreate the directory after every checkout.git reset --hard, commit only the .gitignore change, and allow Git to detect the directory as ignored afterward.git clean -fd .Rproj.user, commit the .gitignore change, and restore the directory from the previous commit..gitignore does not stop tracking — .gitignore only prevents untracked files from being staged. To untrack something Git already knows about, you must explicitly remove it from Git's index (the staging area) while leaving your local files untouched.
This is exactly what git rm -r --cached .Rproj.user does. The --cached flag removes the directory from Git's index only, not from your working tree. After running this command and committing alongside your .gitignore change, Git no longer tracks the directory — and since .gitignore now lists it, future modifications won't appear in git status. Your local files remain intact throughout. That makes A the correct answer.
B is wrong because omitting --cached means git rm -r deletes the directory from your working tree entirely, forcing you to manually recreate it after every checkout — exactly what the developer wants to avoid.
C is wrong because git reset --hard simply reverts your working tree and index to the last commit; it doesn't remove the directory from tracking. Committing only the .gitignore change would leave the directory still tracked, so modifications would continue showing up in git status.
D is wrong because git clean -fd removes untracked files from the working tree — the opposite problem. .Rproj.user is already tracked, so git clean won't touch it.
A useful rule of thumb: whenever you need to "untrack without delete," your instinct should immediately go to git rm --cached.One developer's editor creates a local .scratch-index file in a particular clone. Other team members do not generate this file, and the developer must not change any committed repository files or apply the rule to unrelated repositories.
Where should the developer add the ignore pattern?
.gitignore, followed by a commit shared with the team.git/info/exclude file, which remains local to that repository (correct answer).Rprofile, using an option that suppresses Git status output.gitignore), user-level (global excludes), and clone-level (.git/info/exclude). This question tests whether you can match the developer's specific constraints — local only, no committed changes, no effect on other repositories — to the right layer.
The .git/info/exclude file (C) is the perfect fit here. It lives inside the hidden .git folder of a single clone, meaning it is never committed, never pushed, and never visible to teammates. It's purely local to that one working copy, satisfying every constraint the developer has.
Choice A fails because committing a change to .gitignore shares that rule with the entire team and modifies a tracked file — exactly what the developer must avoid. Teammates who never generate .scratch-index would inherit an irrelevant ignore rule.
Choice B describes the global Git excludes file (typically ~/.config/git/exclude), which applies to every repository the user works with on their machine. The developer's constraint explicitly rules this out — the pattern should not affect unrelated repositories.
Choice D is a distractor that conflates R's configuration system with Git's. An .Rprofile option might influence how R behaves, but it has no mechanism to tell Git to ignore files. These are entirely separate tools.
A useful pattern to remember: whenever a question specifies "local only" and "no committed changes" and "this repository only," those three constraints together point directly to .git/info/exclude — the most narrowly scoped of Git's ignore mechanisms.All .Rhistory files should be ignored throughout a repository except tests/fixtures/.Rhistory, which is an intentional test input. None of these files is currently tracked.
Which ordered pair of .gitignore rules satisfies the requirement?
.Rhistory
!tests/fixtures/.Rhistory (correct answer)!.Rhistory
tests/fixtures/.Rhistory/.Rhistory
!tests/fixtures/.Rhistory.Rhistory
tests/fixtures/.Rhistory.gitignore, the order of rules matters enormously because Git processes them top-to-bottom, and a later rule can override an earlier one. The key mechanic here is that you cannot negate a rule for a file inside an ignored directory — Git won't descend into an ignored folder to check for exceptions. However, since no files are currently tracked, you just need the rules to correctly define what gets ignored going forward.
Answer A works because the first line .Rhistory tells Git to ignore all .Rhistory files anywhere in the repo. The second line !tests/fixtures/.Rhistory then un-ignores that specific file. Because the parent directory tests/fixtures/ is not itself ignored (only the .Rhistory pattern is), Git can still traverse into it and honor the negation. This is the correct pattern for "ignore globally, except one specific file."
Answer B reverses the logic fatally. !.Rhistory would attempt to un-ignore files that were never ignored in the first place, and tests/fixtures/.Rhistory on the second line would only ignore that one specific file — leaving all other .Rhistory files tracked. Completely backwards.
Answer C uses /.Rhistory, which anchors the pattern to the root directory only. This means .Rhistory files nested deeper in the repo (e.g., src/.Rhistory) would not be ignored, failing the "throughout a repository" requirement.
Answer D lists two ignore rules with no negation (!), so tests/fixtures/.Rhistory remains ignored rather than permitted — the opposite of what's needed.
Study tip: Remember the two-step pattern — broad ignore first, then ! negation for the exception — and confirm the parent directory of the exception isn't itself ignored.An R workflow creates an untracked local artifact literally named #session.RData. The team wants a .gitignore rule that matches files with exactly that name wherever they occur, without using a broader wildcard.
Which entry correctly represents that filename?
\#session.RData/#session.RData\#session.RData (correct answer)\#session.RData*.gitignore files, you need to understand two things: how Git interprets special characters, and how pattern matching works. This question tests both.
The # character has special meaning in .gitignore — any line beginning with # is treated as a comment and ignored entirely by Git. So if you want Git to literally match a filename that starts with #, you must escape the hash using a backslash (\). This tells Git to treat the # as a plain character rather than a comment marker.
Answer C, \#session.RData, does exactly this. The leading backslash escapes the #, signaling to Git that this is a literal filename pattern, and the rest of the pattern matches the exact filename with no extra wildcards — precisely what the question asks for.
Answer B, #session.RData, looks intuitive but fails immediately: because the line starts with #, Git reads the entire entry as a comment and never processes it as a rule. The file would remain untracked and unignored.
Answer A, \#session.RData/, adds a trailing slash, which in .gitignore syntax matches only directories, not files. Since #session.RData is a file, this rule would never trigger.
Answer D, \#session.RData*, appends a wildcard (*), which would match files like #session.RData_backup or #session.RDataOld — too broad for the requirement of matching exactly that filename.
A useful tip: whenever a filename starts with a Git-special character like # or !, your first instinct should be to reach for the backslash escape.A repository may contain nested example projects, each with its own .Rproj.user directory. The team wants to exclude only the .Rproj.user directory at the repository root because the nested directories are test fixtures.
Which root-level .gitignore entry most precisely implements this policy?
.Rproj.user/.Rproj.user/ (correct answer)**/.Rproj.user/*.Rproj.user/.gitignore patterns, the key distinction to internalize is how Git interprets leading slashes, trailing slashes, and wildcards — because small differences in syntax produce dramatically different matching behavior.
The goal here is to ignore .Rproj.user only at the repository root, leaving nested instances untouched. Option B, /.Rproj.user/, accomplishes exactly this. The leading slash anchors the pattern to the root of the repository, so Git only matches a directory named .Rproj.user sitting directly at the top level. The trailing slash confirms it must be a directory, not a file. Together, these two characters make the pattern as precise as possible.
Option A, .Rproj.user (no slashes), matches any file or directory with that name anywhere in the repository — root, nested, or deeply buried. This would accidentally ignore all the test fixture directories, violating the stated policy.
Option C, **/.Rproj.user/, uses the double-star wildcard to match .Rproj.user/ directories at any depth, which is the opposite of what you want — it explicitly targets every nested occurrence along with the root one.
Option D, *.Rproj.user/, uses a wildcard prefix, which would match directories whose names end in .Rproj.user (like my.Rproj.user/). It doesn't even reliably match .Rproj.user/ itself in all Git implementations, and it certainly doesn't anchor to the root.
A handy rule of thumb: in .gitignore, a leading slash = root-anchored, a trailing slash = directories only, and no leading slash = matches everywhere. Memorize that trio and these questions become straightforward.The root .gitignore contains *.log. A tracked directory named reports/ contains its own .gitignore with !final.log. Three currently untracked files are created: final.log at the repository root, reports/final.log, and reports/draft.log.
Which file is eligible to be added normally with git add, assuming no other ignore rules apply?
final.log filereports/final.log file (correct answer)final.log.gitignore files in Git, the key concept to understand is scope and precedence: a negation rule (!pattern) in a subdirectory's .gitignore can only un-ignore files that weren't already ignored by a parent-level rule — but only if the parent rule didn't already exclude the directory itself. More importantly, a negation in a child .gitignore cannot override an ignore pattern from a higher-level .gitignore.
Here's how the rules apply: The root .gitignore declares *.log, which means every .log file anywhere in the repository is ignored by default. Inside reports/, the local .gitignore adds !final.log, which attempts to un-ignore reports/final.log. Because reports/ itself is a tracked directory (not ignored), Git does process that nested .gitignore — and a negation within the same scope as the match is valid. The !final.log in reports/.gitignore successfully overrides the root *.log rule for files within that folder, making reports/final.log eligible for staging.
A is wrong because the root final.log matches *.log and has no negation rule at that level — it remains ignored. C is wrong for the same reason: the root-level final.log cannot be un-ignored by a rule living in a subdirectory. D is wrong because reports/draft.log still matches *.log and no negation covers it.
As a study tip, remember: negation rules only work within their own .gitignore's scope or lower — a child rule can un-ignore within its directory, but nothing rescues a file ignored at a higher level without a negation at that same level or higher.