Repository access and collaborators¶
The homelab inventory lists the machines of Sam's house, their addresses, and soon the details of the internet connection. Nobody else should read it, but Alex, who helps with the servers, must be able to change it. GitHub separates the two questions: visibility decides who can see a repository, and access decides who can change it.
Why restrict access¶
Typical reasons to keep a repository private:
- Personal or sensitive data: names, addresses, network details, customer records. Personally identifiable information must not be published, and is often protected by law (GDPR in Europe).
- Commercial work: the code of a product a company sells or uses internally.
- Security: configuration files that describe how a system is built help an attacker, even without passwords.
- Work in progress: a project that is not ready to be shown.
For the homelab:
| File | Content | Sensitive because... |
|---|---|---|
inventory.csv |
Hostnames, IP addresses, roles | Maps the internal network of a house |
services.md |
Which service runs where | Tells an attacker what to target |
isp.md (future) |
Public IP, router model, support contract | Identifies the house and its equipment |
Private repositories¶
Choose Private when creating the repository, or later in Settings > General > Danger Zone > Change visibility. A private repository shows a Private badge next to its name, and is visible only to its owner and the people with access.
Anyone else, signed in or not, gets GitHub's 404 page ("This is not the web page you are looking for") at its URL. GitHub answers "not found" rather than "forbidden", so that the very existence of the repository stays secret.
From the terminal, cloning a private repository over HTTPS asks for credentials, even if you have access: see Authenticating with personal access tokens.
Changing visibility
- Private to public: everything becomes readable at once, including the whole history. Check that no commit ever contained a secret.
- Public to private: existing forks and clones made by others are not deleted; GitHub only stops showing the repository to them.
GitHub asks you to confirm the change, and to type the repository name.
Collaborators¶
On a repository owned by a personal account, the only access level besides the owner is collaborator. A collaborator can:
- read the repository (even private), clone it, and push to it;
- create branches, edit files in the browser, and open, review, and merge pull requests;
- manage issues: open, comment, label, assign, close.
A collaborator cannot change the settings of the repository, add or remove other collaborators, change the visibility, or delete the repository: these remain with the owner. With GitHub Free, a repository can have unlimited collaborators, public or private.
Adding a collaborator¶
- In the repository, open Settings > Collaborators (in the Access section of the side menu). GitHub may ask you to confirm your password or 2FA.
- The Who has access box summarizes the visibility and the number of people with direct access.
- Under Manage access, click Add people.
- Search by username, full name, or email, select the person, then click Add
alex-martinto this repository.
The person receives an invitation, by email and in their GitHub notifications, and appears as Pending invite in the list. They become a collaborator only once they accept it. An invitation expires after 7 days; it can be cancelled before that.
sequenceDiagram
participant S as Sam (owner)
participant G as GitHub
participant A as Alex
S->>G: Settings > Collaborators > Add people > alex-martin
G-->>A: Invitation (email and notification)
A->>G: Accept invitation
G-->>S: Alex appears as collaborator
A->>G: Clone, push, open pull requests
S->>G: Remove (when access is no longer needed)
To remove a collaborator, use the Remove button next to their name in the same list. They immediately lose access to a private repository; their existing clones are not deleted.
Organizations and roles¶
In a repository owned by an organization, access is finer. Each person or team receives one of five roles:
| Role | Typical user | Can do (on top of the previous role) |
|---|---|---|
| Read | Someone who only needs to view or discuss | Read and clone, open issues, comment |
| Triage | Someone who organizes the issues | Manage issues and pull requests: labels, assignees, close, reopen, without write access |
| Write | A contributor | Push to the repository, merge pull requests |
| Maintain | A project manager | Manage some settings (topics, wiki, Pages), without destructive or sensitive actions |
| Admin | The owner of the project | Full control: settings, security, access, deletion |
In an organization, access is managed in Settings > Collaborators and teams. People from outside the organization can be added to a single repository as outside collaborators.
Least privilege
Give each person the lowest role that lets them do their job, and remove access when it is no longer needed. Fewer people with write or admin access means fewer accounts that can damage the repository if compromised.
Summary¶
| Need | Solution |
|---|---|
| Hide a repository from everyone else | Private visibility |
| Change visibility | Settings > General > Danger Zone > Change visibility |
| Let someone change a personal repository | Settings > Collaborators > Add people, then they accept |
| Cancel an access | Remove next to the collaborator |
| Fine-grained access | An organization, with roles Read, Triage, Write, Maintain, Admin |
Common mistakes¶
- Expecting an error message about permissions for a private repository. GitHub answers 404, as if it did not exist.
- Thinking the person has access as soon as you click Add. They must accept the invitation, within 7 days.
- Making a private repository public without checking the history. Old commits become public too.
- Leaving former helpers as collaborators. Remove access that is no longer needed.
Hands-on labs¶
Three labs, from guided to more autonomous. They need your GitHub account; Lab 1 also uses the terminal, and Lab 3 works best with a second account (a friend's, or your own second account). Replace <username> with your GitHub username.
Lab 1: a private repository, seen from outside¶
Objective: create a private repository, and observe what someone without access sees, in the browser and with Git.
Prerequisites and initial state: a GitHub account, Git installed, a browser with a private (incognito) window.
Setup: on GitHub, create a private repository homelab-practice-6 with a README. Then:
mkdir -p ~/git-practice/private && cd ~/git-practice/private
Tasks:
- On the repository page, find the visibility badge.
- Open Settings > Collaborators and read the Who has access box.
- Copy the repository URL, and open it in a private window, where you are not signed in. Note the result.
- In the terminal, try to clone the repository over HTTPS. When Git asks for a username, press Ctrl+C.
- Compare with a clone of a public repository, such as
https://github.com/octocat/Hello-World.git.
Expected result and verification:
- The badge reads Private; Who has access shows a private repository with no direct access besides yours.
- The private window shows GitHub's 404 page, not a "permission denied" page.
- The clone of the private repository stops at
Username for 'https://github.com':; the clone of the public repository succeeds without any question.
Solution
cd ~/git-practice/private
git clone https://github.com/<username>/homelab-practice-6.git
# Username for 'https://github.com': <- Ctrl+C
git clone https://github.com/octocat/Hello-World.git
- Git cannot tell whether the repository exists: GitHub answers the same way for a private repository and for a missing one, and Git asks for credentials.
- If a credential manager is already configured on your machine, Git may not ask anything and the clone may succeed: it uses your saved credentials.
Keep homelab-practice-6 for the next labs. Clean up: rm -rf ~/git-practice/private.
Lab 2: going public, and back¶
Objective: change the visibility of a repository in both directions, and read the warnings GitHub gives.
Prerequisites and initial state: homelab-practice-6 from Lab 1, private.
Tasks:
- Add a file
isp.mdcontainingRouter: example model(fake data only), and commit it. - Make the repository public. Read every warning of the confirmation dialog before confirming.
- Check the URL in a private window again.
- Delete
isp.md. Then make the repository private again. - Answer: during the minutes the repository was public, what could a visitor have copied? Is
isp.mdsafe now?
Expected result and verification:
- After task 2, the badge reads Public, and the private window shows the repository and its files.
- After task 4, the badge reads Private again, and the private window shows a 404 page.
- Task 5: a visitor could have cloned the whole repository, including the commit that added
isp.md. It remains in the history of every copy made while the repository was public; in your own repository, it remains in the history too.
Solution
- Add file > Create new file
isp.md, commit. - Settings > General > Danger Zone > Change visibility, choose public, go through the confirmation steps, and type the repository name.
-
Open
isp.md> ... > Delete file, commit; then Change visibility again, and choose private. -
Visibility is not a time machine: anything that was public may have been copied.
- To make a private project public safely, check the history first, or publish a fresh repository without the old history.
Keep homelab-practice-6 for Lab 3.
Lab 3: invite Alex¶
Objective: play the full life of a collaborator: invitation, acceptance, contribution, and removal.
Prerequisites and initial state: homelab-practice-6, private. Ideally, a second GitHub account ("Alex"): a friend's, or your own second account in another browser. Without one, do the tasks marked (Sam) only.
Tasks:
- (Sam) Invite Alex as a collaborator. Note the status displayed in the list.
- (Alex) Find the invitation (email, notifications, or
https://github.com/<username>/homelab-practice-6/invitations), and accept it. - (Alex) Open the repository: check that it is visible, and try to open its Settings tab.
- (Alex) Create a file
alex.mdcontainingHello from Alex, and commit it tomain. - (Sam) Find Alex's commit in the history. Then remove Alex from the collaborators.
- (Alex) Reload the repository page.
- Without a second account: cancel the pending invitation instead of tasks 2 to 6.
Expected result and verification:
- Task 1: Alex appears with the status Pending invite.
- Task 3: Alex sees the repository, but no Settings tab.
- Task 5: the history shows
Create alex.mdby Alex. After the removal, task 6 shows the 404 page to Alex. - Task 7: the invitation disappears from the list; the invitation link no longer works.
Solution
- Settings > Collaborators > Add people > search the username > Add ... to this repository.
- Alex: Accept invitation.
- Sam: N commits to see the history; then Settings > Collaborators > Remove next to Alex.
-
Settings > Collaborators: the pending invitation has its own cancel option.
-
The collaborator can push and merge, but cannot change settings or invite others: those stay with the owner.
- Removing a collaborator does not delete their clones or their commits: the history keeps Alex as the author of
alex.md.
Clean up when you are done: delete homelab-practice-6 on GitHub (Settings > General > Danger Zone).