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
.gitignore
file: This temporarily saves your.gitignore
file 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
.gitignore
file: This brings your stashed.gitignore
file 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.