Various ways to remove local Git changes
Asked Answered
S

10

710

I just cloned a git repository and checked out a branch. I worked on it, and then decided to remove all my local changes, as I wanted the original copy.

In short, I had to do the following two commands to remove my local changes

git checkout .

git clean -f

My question is,

(1) Is this the correct approach in getting rid of local changes, or else please let me know the correct approach.

(2) when do we use git reset --hard as i am able to reset even without this command

Thanks

*Solution : Major Edit(s): 03/26 : * Replaced many of vague terms with git specific terminology [tracked/untracked/staged/unstaged]

There could be only three categories of files when we make local changes:

Type 1. Staged Tracked files

Type 2. Unstaged Tracked files

Type 3. Unstaged UnTracked files a.k.a UnTracked files

  • Staged - Those that are moved to staging area/ Added to index
  • Tracked - modified files
  • UnTracked - new files. Always unstaged. If staged, that means they are tracked.

What each commands do:

  1. git checkout . - Removes Unstaged Tracked files ONLY [Type 2]

  2. git clean -f - Removes Unstaged UnTracked files ONLY [Type 3]

  3. git reset --hard - Removes Staged Tracked and UnStaged Tracked files ONLY[Type 1, Type 2]

  4. git stash -u - Removes all changes [Type 1, Type 2, Type 3]

Conclusion:

It's clear that we can use either

(1) combination of `git clean -f` and `git reset --hard` 

OR

(2) `git stash -u`

to achieve the desired result.

Note: Stashing, as the word means 'Store (something) safely and secretly in a specified place.' This can always be retrieved using git stash pop. So choosing between the above two options is developer's call.

Thank you Christoph and Frederik Schøning.

Edit: 03/27

I thought it's worth putting the 'beware' note to git clean -f

git clean -f

There is no going back. Use -n or --dry-run to preview the damage you'll do.

If you want to also remove directories, run git clean -f -d

If you just want to remove ignored files, run git clean -f -X

If you want to remove ignored as well as non-ignored files, run git clean -f -x

reference : more on git clean : How to remove local (untracked) files from the current Git working tree?

Edit: 05/20/15

Discarding all local commits on this branch [Removing local commits]

In order to discard all local commits on this branch, to make the local branch identical to the "upstream" of this branch, simply run git reset --hard @{u}

Reference: http://sethrobertson.github.io/GitFixUm/fixup.html

or do git reset --hard origin/master [if local branch is master]

Note: 06/12/2015 This is not a duplicate of the other SO question that's marked as duplicate. This question address how to remove local GIT changes [remove a file added, remove changes added to existing file etc and the various approaches; Where in the other SO thread only address how to remove local commit. If you added a file, and you want to remove that alone, then the other SO thread doesn't discuss about it. Hence this is not a duplicate of the other one]

Edit: 06/23/15

How to revert a commit already pushed to a remote repository?

$ git revert ab12cd15

Edit: 09/01/2015

Delete a previous commit from local branch and remote branch

Case: You just commited a change to your local branch and immediately pushed to the remote branch, Suddenly realized , Oh no! I dont need this change. Now do what?

git reset --hard HEAD~1 [for deleting that commit from local branch]

git push origin HEAD --force [both the commands must be executed. For deleting from remote branch]

Whats the branch ? Its the currently checked out branch.

Edit 09/08/2015 - Remove local git merge:

I am on master branch and merged master branch with a newly working branch phase2

$ git status
# On branch master

$ git merge phase2

$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 8 commits.

Q: How to get rid of this merge? Tried git reset --hard and git clean -d -f Both didn't work.

The only thing that worked are any of the below ones:

$ git reset --hard origin/master

or

$ git reset --hard HEAD~8

or

$ git reset --hard 9a88396f51e2a068bb7 [sha commit code - this is the one that was present before all your merge commits happened]

Soria answered 24/3, 2014 at 20:54 Comment(10)
I guess this thread might answer your questions: #1147473Motorman
"git stash" will remove any changes you have made.Clodhopping
Nice summary! I'd add another file category: "Type 4. Ignored files." git stash -a [or --all] will stash the ignored and untracked files as well. git clean -x will clean ignored files as well. git clean -X will clean only the ignored files.Deckard
possible duplicate of Throw away local commits in gitPhilae
@JavaDev Your question was more like an answer.. appreciate that you kept on editing and compiled all the answers.Suicide
git checkout -f removes tracked and untracked files.Bandur
thanks i ran all 4 of your commands to reverse local changesChow
But these solutions don't seem to remove my git ignored files, i.e. files and folders inside .gitignore (which may make sense ;-). Do I have to remove these manually (or at least remove them from .gitignore)?Longsufferance
git reset origin/<name-of-your-branch> --hardWhisk
This is pretty much "just how Git works" but saying that git clean -f is a way to restore a repo is incomplete to the point of misleading. (Obviously these details are there buried in the discussion.) But git clean -f will only clean a certain class of changes. Notable, it WILL NOT fix creation of directories, and there are complications relating to ignored files. (I don't know about you, but I'm pretty likely to have a directory created by running a build, or just because I stash some stuff.) So, in summary, in general, git clean -f IS NOT the answer to the question.Eleazar
D
560

It all depends on exactly what you are trying to undo/revert. Start out by reading the post in Ube's link. But to attempt an answer:

Hard reset

git reset --hard [HEAD]

completely remove all staged and unstaged changes to tracked files.

I find myself often using hard resetting, when I'm like "just undo everything like if I had done a complete re-clone from the remote". In your case, where you just want your repo pristine, this would work.

Clean

git clean [-f]

Remove files that are not tracked.

For removing temporary files, but keep staged and unstaged changes to already tracked files. Most times, I would probably end up making an ignore-rule instead of repeatedly cleaning - e.g. for the bin/obj folders in a C# project, which you would usually want to exclude from your repo to save space, or something like that.

The -f (force) option will also remove files, that are not tracked and are also being ignored by git though ignore-rule. In the case above, with an ignore-rule to never track the bin/obj folders, even though these folders are being ignored by git, using the force-option will remove them from your file system. I've sporadically seen a use for this, e.g. when scripting deployment, and you want to clean your code before deploying, zipping or whatever.

Git clean will not touch files, that are already being tracked.

Checkout "dot"

git checkout .

I had actually never seen this notation before reading your post. I'm having a hard time finding documentation for this (maybe someone can help), but from playing around a bit, it looks like it means:

"undo all changes in my working tree".

I.e. undo unstaged changes in tracked files. It apparently doesn't touch staged changes and leaves untracked files alone.

Stashing

Some answers mention stashing. As the wording implies, you would probably use stashing when you are in the middle of something (not ready for a commit), and you have to temporarily switch branches or somehow work on another state of your code, later to return to your "messy desk". I don't see this applies to your question, but it's definitely handy.

To sum up

Generally, if you are confident you have committed and maybe pushed to a remote important changes, if you are just playing around or the like, using git reset --hard HEAD followed by git clean -f will definitively cleanse your code to the state, it would be in, had it just been cloned and checked out from a branch. It's really important to emphasize, that the resetting will also remove staged, but uncommitted changes. It will wipe everything that has not been committed (except untracked files, in which case, use clean).

All the other commands are there to facilitate more complex scenarios, where a granularity of "undoing stuff" is needed :)

I feel, your question #1 is covered, but lastly, to conclude on #2: the reason you never found the need to use git reset --hard was that you had never staged anything. Had you staged a change, neither git checkout . nor git clean -f would have reverted that.

Hope this covers.

Duclos answered 24/3, 2014 at 21:57 Comment(11)
Thank you for the reason behind using git reset --hard. I tried it out, and yes.. those files added to index(staging) were removed only after git reset --hard, and i assume by default git reset --hard is git reset --hard head. This link was also helpful gitready.com/beginner/2009/01/18/the-staging-area.htmlSoria
I improved my answer why I think git stash -u makes most sense here.Lengthwise
Yes, git reset --hard is shorthand for git reset --hard HEAD (see kernel.org/pub/software/scm/git/docs/git-reset.html, examples section). Christoph: you have a valid point - git stash -u is indeed the only single command to clean stuff up. And, obviously, you can pop the stash back up. But it is saved somewhere in storage/index (say for example you stashed sensitive information, now ready for others to peek), and semantically it's maybe not exactly the equivalent of cleaning your repo. But: it works - in 1 command ;)Patino
Alternatively, for a single-liner, you could make a bat/shell file to execute the chained command git reset --hard && git clean [-f]. This would remove all changes (tracked, untracked, staged, unstaged), never to be found again.Patino
Thank you both of you. I have summarized the answer and embedded into my question. Christoph let me know what git stash -u does and how to pop it, but Frederik let me know reset hard and using the combination of git reset --hard and git clean -f , and why not stash is preferred in some scenarios. Now Please help me in choosing which one should i mark as Answer :) , both are my answers.Soria
. is a pathspec referring to the current working directory, which might be the root of the repo. From git-scm.com: git checkout [<tree-ish>] [--] <pathspec>… updates the named paths in the working tree from the index file or from a named <tree-ish>.Deckard
git-scm.com/docs/git-clean explains the git clean args differently. -f (force) is normally needed to get it to delete anything. -x also removes ignored files. -X only removes ignored files. -d also removes untracked directories.Deckard
It's never enough stressed that both git reset --hard and git clean -dfx and the like are destructive. Anyway, please fix the lowercase head in the answer, it should be either uppercase HEAD or not present at all.Latinism
If you do this and still find that you have some local changes in your directory, its because those are untracked files. Do git add . and then git reset --hardBorman
These commands don't work for me at all, just generates errors.Brittnybritton
git checkout . seems like a nice solution.Allayne
S
35

Reason for adding an answer at this moment:

So far I was adding the conclusion and ‘answers’ to my initial question itself, making the question very lengthy, hence moving to separate answer.

I have also added more frequently used git commands that helps me on git, to help someone else too.

Basically to clean all local commits $ git reset --hard and $ git clean -d -f


First step before you do any commits is to configure your username and email that appears along with your commit.

#Sets the name you want attached to your commit transactions

$ git config --global user.name "[name]"

#Sets the email you want atached to your commit transactions

$ git config --global user.email "[email address]"

#List the global config

$ git config --list

#List the remote URL

$ git remote show origin

#check status

git status

#List all local and remote branches

git branch -a

#create a new local branch and start working on this branch

git checkout -b "branchname" 

or, it can be done as a two step process

create branch: git branch branchname work on this branch: git checkout branchname

#commit local changes [two step process:- Add the file to the index, that means adding to the staging area. Then commit the files that are present in this staging area]

git add <path to file>

git commit -m "commit message"

#checkout some other local branch

git checkout "local branch name"

#remove all changes in local branch [Suppose you made some changes in local branch like adding new file or modifying existing file, or making a local commit, but no longer need that] git clean -d -f and git reset --hard [clean all local changes made to the local branch except if local commit]

git stash -u also removes all changes

Note: It's clear that we can use either (1) combination of git clean –d –f and git reset --hard OR (2) git stash -u to achieve the desired result.

Note 1: Stashing, as the word means 'Store (something) safely and secretly in a specified place.' This can always be retreived using git stash pop. So choosing between the above two options is developer's call.

Note 2: git reset --hard will delete working directory changes. Be sure to stash any local changes you want to keep before running this command.

# Switch to the master branch and make sure you are up to date.

git checkout master

git fetch [this may be necessary (depending on your git config) to receive updates on origin/master ]

git pull

# Merge the feature branch into the master branch.

git merge feature_branch

# Reset the master branch to origin's state.

git reset origin/master

#Accidentally deleted a file from local , how to retrieve it back? Do a git status to get the complete filepath of the deleted resource

git checkout branchname <file path name>

that's it!

#Merge master branch with someotherbranch

git checkout master
git merge someotherbranchname

#rename local branch

git branch -m old-branch-name new-branch-name

#delete local branch

git branch -D branch-name

#delete remote branch

git push origin --delete branchname

or

git push origin :branch-name

#revert a commit already pushed to a remote repository

git revert hgytyz4567

#branch from a previous commit using GIT

git branch branchname <sha1-of-commit>

#Change commit message of the most recent commit that's already been pushed to remote

git commit --amend -m "new commit message"
git push --force origin <branch-name>

# Discarding all local commits on this branch [Removing local commits]

In order to discard all local commits on this branch, to make the local branch identical to the "upstream" of this branch, simply run

git reset --hard @{u}

Reference: http://sethrobertson.github.io/GitFixUm/fixup.html or do git reset --hard origin/master [if local branch is master]

# Revert a commit already pushed to a remote repository?

$ git revert ab12cd15

#Delete a previous commit from local branch and remote branch

Use-Case: You just commited a change to your local branch and immediately pushed to the remote branch, Suddenly realized , Oh no! I dont need this change. Now do what?

git reset --hard HEAD~1 [for deleting that commit from local branch. 1 denotes the ONE commit you made]

git push origin HEAD --force [both the commands must be executed. For deleting from remote branch]. Currently checked out branch will be referred as the branch where you are making this operation.

#Delete some of recent commits from local and remote repo and preserve to the commit that you want. ( a kind of reverting commits from local and remote)

Let's assume you have 3 commits that you've pushed to remote branch named 'develop'

commitid-1 done at 9am
commitid-2 done at 10am
commitid-3 done at 11am. // latest commit. HEAD is current here.

To revert to old commit ( to change the state of branch)

git log --oneline --decorate --graph // to see all your commitids

git clean -d -f // clean any local changes

git reset --hard commitid-1 // locally reverting to this commitid

git push -u origin +develop // push this state to remote. + to do force push

# Remove local git merge: Case: I am on master branch and merged master branch with a newly working branch phase2

$ git status

On branch master

$ git merge phase2 $ git status

On branch master

Your branch is ahead of 'origin/master' by 8 commits.

Q: How to get rid of this local git merge? Tried git reset --hard and git clean -d -f Both didn't work. The only thing that worked are any of the below ones:

$ git reset --hard origin/master

or

$ git reset --hard HEAD~8

or

$ git reset --hard 9a88396f51e2a068bb7 [sha commit code - this is the one that was present before all your merge commits happened]

#create gitignore file

touch .gitignore // create the file in mac or unix users

sample .gitignore contents:

.project
*.py
.settings

Reference link to GIT cheat sheet: https://services.github.com/on-demand/downloads/github-git-cheat-sheet.pdf

Soria answered 18/9, 2015 at 21:18 Comment(3)
Your command for Deleting Remote Branch might be not best. You are using git push origin :branch-name however I recommend using git push origin --delete branchnameNegatron
Agree, i updated with your suggestion, thank you @NegatronSoria
This answer is closer than above, because it includes -d in git clean -d -f I didn't run into the problem of ignored files (yet) but it is extremely likely users will have created directories that need to be deleted. For the ignored file issue, you probably want -x. In summary, the answer is git clean -fdx (Like with most things git, the default is not what you want.) As for "stash" doing what is requested. Maybe so. But it has the side effect of creating a stash. (If that is some 200GB file you accidentally created, you would probably care. A lot.) So that should be noted.Eleazar
L
24

As with everything in git there are multiple ways of doing it. The two commands you used are one way of doing it. Another thing you could have done is simply stash them with git stash -u. The -u makes sure that newly added files (untracked) are also included.

The handy thing about git stash -u is that

  1. it is probably the simplest (only?) single command to accomplish your goal
  2. if you change your mind afterwards you get all your work back with git stash pop (it's like deleting an email in gmail where you can just undo if you change your mind afterwards)

As of your other question git reset --hard won't remove the untracked files so you would still need the git clean -f. But a git stash -u might be the most convenient.

Lengthwise answered 24/3, 2014 at 21:10 Comment(4)
git reset --hardwill not remove untracked files indeed, but it will remove untracked changes, i.e. changes to files, that are already in the index. I'm sure that's what you meant :)Patino
When i used git stash -u, i saw this response from git bash. "Saved working directory and index state WIP on {branchname} . May be this saved one is what we could retrieve using git stash pop.Soria
Thank you both of you. I have summarized the answer and embedded into my question. Christoph let me know what git stash -u does and how to pop it, but Frederik let me know reset hard and using the combination of git reset --hard and git clean -f , and why not stash is preferred in some scenarios. Now Please help me in choosing which one should i mark as Answer :) , both are my answers.Soria
but what if there is a file I added to my repository that I don't want to track? only in my repo. If I add it to the ignore list then I have a .ignore file to commit which will effect everyone else as well.Hunsinger
J
9

1. When you don't want to keep your local changes at all.

git reset --hard

This command will completely remove all the local changes from your local repository. This is the best way to avoid conflicts during pull command, only if you don't want to keep your local changes at all.

2. When you want to keep your local changes

If you want to pull the new changes from remote and want to ignore the local changes during this pull then,

git stash

It will stash all the local changes, now you can pull the remote changes,

git pull

Now, you can bring back your local changes by,

git stash pop
Juju answered 4/11, 2016 at 10:46 Comment(1)
git reset --hard does not remove all local changes. It only removes the modifications. If you want to remove adds, then you must also git clean -fdInitiatory
C
6

I think git has one thing that isn't clearly documented. I think it was actually neglected.

git checkout .

Man, you saved my day. I always have things I want to try using the modified code. But the things sometimes end up messing the modified code, add new untracked files etc. So what I want to do is, stage what I want, do the messy stuff, then cleanup quickly and commit if I'm happy.

There's git clean -fd works well for untracked files.

Then git reset simply removes staged, but git checkout is kinda too cumbersome. Specifying file one by one or using directories isn't always ideal. Sometimes the changed files I want to get rid of are within directories I want to keep. I wished for this one command that just removes unstaged changes and here you're. Thanks.

But I think they should just have git checkout without any options, remove all unstaged changes and not touch the the staged. It's kinda modular and intuitive. More like what git reset does. git clean should also do the same.

Cumulonimbus answered 8/3, 2018 at 21:14 Comment(0)
B
4

Use:

git checkout -- <file>

To discard the changes in the working directory.

Backpack answered 26/6, 2017 at 13:57 Comment(0)
B
2

The best way is checking out the changes.

Changing the file pom.xml in a project named project-name you can do it:

git status

# modified:   project-name/pom.xml

git checkout project-name/pom.xml
git checkout master

# Checking out files: 100% (491/491), done.
# Branch master set up to track remote branch master from origin.
# Switched to a new branch 'master'
Boardman answered 15/1, 2015 at 17:1 Comment(0)
M
2

For discard all i like to stash and drop that stash, it's the fastest way to discard all, especially if you work between multiple repos.

This will stash all changes in {0} key and instantly drop it from {0}

git stash && git stash drop

Melli answered 27/6, 2017 at 16:26 Comment(0)
T
1

First of all check is your important change saved or not by:

$ git status

than try

$ git reset --hard

it will reset your branch to default

but if you need just undo:

$ edit (1) $ git add frotz.c filfre.c $ mailx (2) $ git reset
(3) $ git pull git://info.example.com/ nitfol


Read more >> https://git-scm.com/docs/git-reset

Tilton answered 21/9, 2017 at 11:2 Comment(1)
Side note: reset --hard is dangerous command this will remove all the changes and it cant be undone. The user should be aware when using reset hard.Interrelated
H
1

Option 1: Discard tracked and untracked file changes

Discard changes made to both staged and unstaged files.

$ git reset --hard [HEAD]

Then discard (or remove) untracked files altogether.

$ git clean [-f]

Option 2: Stash

You can first stash your changes

$ git stash

And then either drop or pop it depending on what you want to do. See https://git-scm.com/docs/git-stash#_synopsis.

Option 3: Manually restore files to original state

First we switch to the target branch

$ git checkout <branch-name>

List all files that have changes

$ git status

Restore each file to its original state manually

$ git restore <file-path>
Herrmann answered 21/12, 2020 at 18:59 Comment(1)
for the first option do git clean -fdx if you want to remove also directories. -x is a bit dangerous, see here, since it removes ignored files tooDab

© 2022 - 2024 — McMap. All rights reserved.