Skip to main content

Overview

Dependify uses a “temporary staging fork” approach when working with repositories you don’t own. This guide explains the fork lifecycle, automatic detection logic, and cleanup process.
Forks are only created for external repositories. If you own the repository, Dependify creates a branch directly in your repo—no fork needed.

The Temporary Staging Fork Concept

What is a Temporary Staging Fork?

A temporary staging fork is:
  • A short-lived fork created solely to propose changes via pull request
  • Not intended for long-term use or independent development
  • Safe to delete after the PR is merged or closed
  • Automatically created by Dependify when modernizing external repositories
Think of it like a staging area in Git—temporary storage for changes before they’re committed to the main repository.

Why Forks Are Necessary

GitHub’s permission model requires forks for contributing to external repositories:
Scenario: You want to modernize microsoft/magma

Without Fork:
❌ Cannot push branches to microsoft/magma (no write access)
❌ Cannot create PR from non-existent branch

With Fork:
✅ Create your-username/magma fork
✅ Push changes to your fork
✅ Create PR from your-username/magma to microsoft/magma

Automatic Fork Detection Logic

Step-by-Step Detection Process

Dependify follows this logic when you submit a repository:
# From git_driver.py:11-86

def create_fork(repo_owner, repo_name):
    # Step 1: Get authenticated user's username
    user_response = requests.get("https://api.github.com/user")
    username = user_response.json()["login"]
    
    # Step 2: Check if user owns the repository
    if username.lower() == repo_owner.lower():
        print(f"User owns the repository - no fork needed")
        return repo_data  # is_own_repo = True
    
    # Step 3: Check if fork already exists
    fork_check_url = f"https://api.github.com/repos/{username}/{repo_name}"
    fork_response = requests.get(fork_check_url)
    
    if fork_response.status_code == 200:
        fork_data = fork_response.json()
        if fork_data.get("fork"):
            print(f"Fork already exists: {fork_data['clone_url']}")
            return fork_data  # Use existing fork
    
    # Step 4: Create new fork
    url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/forks"
    response = requests.post(url)
    
    if response.status_code == 202:
        print("New fork created successfully")
        return response.json()
Dependify queries GitHub’s API to get your authenticated username.
GET https://api.github.com/user
# Returns: { "login": "your-username", ... }
Compares your username with the repository owner (case-insensitive).
if username.lower() == repo_owner.lower():
    # You own it → No fork needed
    return original_repo_data
Looks for an existing fork under your account.
GET https://api.github.com/repos/your-username/repo-name
# If exists and is a fork → Reuse it
If no fork exists, creates a new one.
POST https://api.github.com/repos/original-owner/repo-name/forks
# Returns 202: Fork creation initiated

When Forks Are Created vs Direct PR

Decision Tree

Repository: github.com/owner/repo
|
├─ Do you own it? (your-username == owner)
│  ├─ YES → Direct Branch + PR in your repo
│  │        No fork created
│  │        Branch: dependify-xxxxx
│  │        PR: owner/repo (dependify-xxxxx → main)
│  │
│  └─ NO → Fork Required
│     |
│     ├─ Fork exists? (your-username/repo)
│     │  ├─ YES → Use existing fork
│     │  │        Clone: your-username/repo
│     │  │        Push changes to your fork
│     │  │        PR: owner/repo (your-username:dependify-xxxxx → main)
│     │  │
│     │  └─ NO → Create new fork
│     │           Fork: your-username/repo
│     │           Clone: your-username/repo
│     │           Push changes to your fork
│     │           PR: owner/repo (your-username:dependify-xxxxx → main)

Comparison Table

ScenarioFork Created?Branch LocationPR Format
Your own repo❌ Noyour-username/repo:dependify-xxxrepo (branch → main)
External repo (no fork)✅ Yesyour-username/repo:dependify-xxxoriginal-repo (fork:branch → main)
External repo (fork exists)♻️ Reusedyour-username/repo:dependify-xxxoriginal-repo (fork:branch → main)

Fork Lifecycle

1. Fork Creation

# Dependify executes:
POST /repos/original-owner/repo-name/forks

# GitHub responds:
HTTP 202 Accepted
{
  "name": "repo-name",
  "owner": { "login": "your-username" },
  "fork": true,
  "parent": {
    "full_name": "original-owner/repo-name"
  }
}
Your fork appears at: github.com/your-username/repo-name
  • ✅ All branches (including default branch)
  • ✅ Commit history
  • ✅ Tags and releases
  • ❌ Issues (not copied)
  • ❌ Pull requests (not copied)
  • ❌ Actions workflows (disabled by default)

2. Fork Usage

# From git_driver.py:344-386

# Clone the fork with authentication
authenticated_url = fork_url.replace(
    "https://github.com/",
    f"https://{Config.GITHUB_TOKEN}@github.com/"
)

repo = Repo.clone_from(authenticated_url, staging_dir)

# Create and checkout new branch
new_branch_name = f"dependify-{uuid.uuid4().hex[:8]}"
new_branch = repo.create_head(new_branch_name)
new_branch.checkout()

# Make changes, commit, and push
repo.index.add(files_to_stage)
repo.index.commit("🤖 Automated code modernization by Dependify")
origin.push(new_branch)
Dependify clones your fork (not the original repo) to ensure changes can be pushed without permission errors.

3. Pull Request Creation

PR is created from your fork to the original repository:
# From git_driver.py:262-269

if is_own_repo:
    head = new_branch_name  # Just "dependify-xxxxx"
else:
    head = f"{head_owner}:{new_branch_name}"  # "your-username:dependify-xxxxx"

data = {
    "title": "🤖 Automated code modernization by Dependify",
    "head": head,
    "base": base_branch,  # Usually "main"
    "body": pr_body
}
Result: PR appears in the original repository, sourced from your fork.

4. Fork Cleanup (Optional)

After the PR is merged or closed, you can delete the fork:
# From git_driver.py:305-340

def delete_fork(repo_owner, repo_name):
    """
    Delete a forked repository (OPTIONAL - for cleanup after PR is merged).
    
    Users can also manually delete forks from GitHub UI.
    """
    url = f"https://api.github.com/repos/{repo_owner}/{repo_name}"
    response = requests.delete(url, headers=headers)
    
    if response.status_code == 204:
        print(f"✅ Fork deleted: {repo_owner}/{repo_name}")
        return True
Fork deletion is permanent and irreversible. Only delete forks after the PR is merged or closed, and you’re certain you don’t need the fork anymore.

Fork Cleanup After PR is Merged

You can manually delete forks through GitHub’s web interface:
  1. Navigate to your fork: github.com/your-username/repo-name
  2. Click Settings (repository settings)
  3. Scroll to Danger Zone
  4. Click Delete this repository
  5. Confirm deletion by typing the repository name
Manual deletion gives you control and ensures you don’t accidentally delete a fork you still need.

When to Delete Your Fork

PR has been merged into the original repository
PR has been closed (rejected or abandoned)
You don’t plan to contribute again soon
All your changes are in the original repo
⚠️ PR is still open and under review
⚠️ You plan to make more contributions to the same project
⚠️ You want to maintain your own version of the project
⚠️ Fork has additional branches you’re working on

Automated Cleanup (Future Feature)

Automated fork cleanup is on the roadmap for future versions of Dependify. Currently, you need to manually delete forks through GitHub.

Understanding PR Descriptions for Forked Repos

When Dependify creates a PR from a fork, the description includes fork-specific information:
## Automated Code Modernization

This pull request was automatically generated by Dependify...

### About This PR
- This PR was created from a **temporary staging fork** (`your-username/repo-name`)
- The fork was created solely to propose these changes
- You can safely delete the fork after reviewing/merging this PR
- All changes are transparent and can be reviewed in the "Files changed" tab

### Branch
`dependify-a3f2d8c1` (from fork: `your-username/repo-name`)

---
Generated with ❤️ by Dependify 2.0

*Note: This is an automated tool for code modernization. The temporary fork
used to create this PR can be deleted after the PR is merged or closed.*
The PR description explicitly mentions the temporary fork to help repository maintainers understand where the changes came from.

Common Fork Scenarios

Scenario 1: First-Time Contribution

Input: https://github.com/facebook/react

1. ✅ Dependify detects you don't own facebook/react
2. ✅ No fork exists → Creates your-username/react
3. ✅ Clones your fork
4. ✅ Creates branch: dependify-x8a4b7f2
5. ✅ Pushes changes to your fork
6. ✅ Opens PR: facebook/react ← your-username:dependify-x8a4b7f2

Result: PR submitted! Fork created at github.com/your-username/react

Scenario 2: Fork Already Exists

Input: https://github.com/facebook/react
(You previously forked this repository)

1. ✅ Dependify detects you don't own facebook/react
2. ✅ Fork exists → Reuses your-username/react
3. ✅ Clones your existing fork
4. ✅ Creates branch: dependify-c2d9e6f1
5. ✅ Pushes changes to your fork
6. ✅ Opens PR: facebook/react ← your-username:dependify-c2d9e6f1

Result: PR submitted using existing fork!

Scenario 3: Multiple PRs from Same Fork

First Run:
- Creates fork: your-username/repo
- Branch: dependify-aaa111
- PR #1: Modernizes JavaScript files

Second Run (same repo):
- Reuses fork: your-username/repo
- Branch: dependify-bbb222
- PR #2: Modernizes TypeScript files

Both PRs coexist from the same fork!
You can have multiple open PRs from the same fork by using different branch names. Each dependify-xxxxx branch is unique.

Troubleshooting Fork Issues

”Failed to create fork: 403 Forbidden”

Repository is private and you don’t have access.
  • Ask the repository owner to add you as a collaborator
  • Ensure you have read access to the repository
  • For private repos, you need explicit permission

”Fork already exists (200 response)”

You’ve previously forked this repository.
  • This is not an error—Dependify will use your existing fork
  • If your fork is outdated, consider syncing it with the original repo first
  • Alternatively, delete your fork and let Dependify create a fresh one

”Error pushing to remote”

Authentication failed or fork permissions issue.
  • Verify your GitHub token has the repo scope
  • Check that your fork isn’t archived or read-only
  • Ensure you have push access to your own fork

”PR creation failed: Validation Failed”

Branch name collision or PR already exists for this branch.
  • Check if a PR already exists for the same branch
  • Close or merge existing PRs before creating new ones
  • Delete the branch in your fork and retry

Best Practices for Fork Management

  • Delete forks after PRs are merged
  • Use descriptive branch names for your own changes
  • Don’t mix Dependify branches with your manual work
If you plan to contribute multiple times:
# Sync your fork with the original repo
git remote add upstream https://github.com/original-owner/repo.git
git fetch upstream
git merge upstream/main
git push origin main
Periodically review and delete old Dependify branches:
# List all dependify branches
git branch -r | grep dependify

# Delete old branches
git push origin --delete dependify-old-branch

Build docs developers (and LLMs) love