Git: Discard All Local Changes and Get a Fresh Copy from GitHub
A common and reliable way to get a fresh copy from a GitHub repository, while preserving specific local files like .gitignore, is to use a combination of git reset and git clean. This approach ensures your local branch exactly mirrors the remote branch, without leaving behind any untracked or unwanted files.
The Right Approach
Your goal is to achieve a state where your local repository is an exact clone of the remote, except for your .gitignore file. Here's the sequence of commands that achieves this:
- Stash your
.gitignorefile: This temporarily saves your.gitignorefile so it won't be deleted. - Forcefully reset your local branch: This discards all commits and changes on your local branch, making it an exact copy of the remote.
- Clean your working directory: This removes all untracked files, which includes things you might have created but not yet committed.
- Restore your
.gitignorefile: This brings your stashed.gitignorefile back into the repository.
Step-by-Step Commands
Let's assume you're on the main branch and want to pull the latest from the origin remote.
Step 2.1: Stash the .gitignore File
First, you need to save your .gitignore file so it doesn't get deleted by the cleanup commands.
git stash push -- .gitignore
This command adds .gitignore to your stash, a temporary storage area for changes.
Step 2.2: Fetch the Latest from Remote
Before resetting, fetch the latest state of the repository from GitHub. This ensures you're resetting to the most current version.
git fetch origin main
This command downloads the latest changes from the main branch on the origin remote without merging them into your local branch.
Step 2.3: Reset to the Remote Branch
Now, you can forcefully reset your local main branch to the exact commit origin/main is pointing to.
git reset --hard origin/main
The --hard flag is crucial as it discards all local commits and uncommitted changes, making your local branch identical to the remote.
Step 2.4: Clean Untracked Files
Next, you need to remove all untracked files from your working directory, except those specified in .gitignore.
git clean -d -f
The -d flag removes untracked directories, and the -f flag forces the operation. git clean respects the .gitignore file, so it won't delete files that are ignored by your repository (1).
Step 2.5: Restore the .gitignore File
Finally, you can restore your .gitignore file from the stash you created in the first step.
git stash pop
This command applies the stashed changes to your working directory and then removes them from the stash.
Alternative for Simple Cases
If your goal is simply to pull the latest changes and a few files are untracked and in the way, you can use the git clean command alone.
# Forcefully remove all untracked files and directories
git clean -f -d
After this, you should be able to run git pull without issues.
Why This is the Best Approach
Using git reset --hard combined with git clean is the most explicit and reliable way to get a clean, up-to-date copy from the remote. It avoids the complexities of merges and ensures no unwanted local files or commits are left behind.
