🕷️ Crawler Inspector

URL Lookup

Direct Parameter Lookup

Raw Queries and Responses

1. Shard Calculation

Query:
Response:
Calculated Shard: 129 (from laksa129)

2. Crawled Status Check

Query:
Response:

3. Robots.txt Check

Query:
Response:

4. Spam/Ban Check

Query:
Response:

5. Seen Status Check

ℹ️ Skipped - page is already crawled

📄
INDEXABLE
✅
CRAWLED
7 hours ago
🤖
ROBOTS ALLOWED

Page Info Filters

FilterStatusConditionDetails
HTTP statusPASSdownload_http_code = 200HTTP 200
Age cutoffPASSdownload_stamp > now() - 6 MONTH0 months ago
History dropPASSisNull(history_drop_reason)No drop reason
Spam/banPASSfh_dont_index != 1 AND ml_spam_score = 0ml_spam_score=0
CanonicalPASSmeta_canonical IS NULL OR = '' OR = src_unparsedNot set

Page Details

PropertyValue
URLhttps://github.blog/open-source/git/how-to-undo-almost-anything-with-git/
Last Crawled2026-04-12 03:54:46 (7 hours ago)
First Indexed2024-06-04 18:29:31 (1 year ago)
HTTP Status Code200
Meta TitleHow to undo (almost) anything with Git - The GitHub Blog
Meta DescriptionOne of the most useful features of any version control system is the ability to "undo" your mistakes. In Git, "undo" can mean many slightly different things.
Meta Canonicalnull
Boilerpipe Text
One of the most useful features of any version control system is the ability to “undo” your mistakes. In Git, “undo” can mean many slightly different things. When you make a new commit, Git stores a snapshot of your repository at that specific moment in time; later, you can use Git to go back to an earlier version of your project. In this post, I’m going to take a look at some common scenarios where you might want to “undo” a change you’ve made and the best way to do it using Git. Undo a “public” change Scenario: You just ran git push , sending your changes to GitHub, now you realize there’s a problem with one of those commits. You’d like to undo that commit. Undo with: git revert <SHA> What’s happening: git revert will create a new commit that’s the opposite (or inverse) of the given SHA. If the old commit is “matter”, the new commit is “anti-matter”—anything removed in the old commit will be added in the new commit and anything added in the old commit will be removed in the new commit. This is Git’s safest, most basic “undo” scenario, because it doesn’t alter history—so you can now git push the new “inverse” commit to undo your mistaken commit. Fix the last commit message Scenario: You just typo’d the last commit message, you did git commit -m "Fxies bug #42" but before git push you realized that really should say “Fixes bug #42”. Undo with: git commit --amend or git commit --amend -m "Fixes bug #42" What’s happening: git commit --amend will update and replace the most recent commit with a new commit that combines any staged changes with the contents of the previous commit. With nothing currently staged, this just rewrites the previous commit message. Undo “local” changes Scenario: The cat walked across the keyboard and somehow saved the changes, then crashed the editor. You haven’t committed those changes, though. You want to undo everything in that file—just go back to the way it looked in the last commit. Undo with: git checkout -- <bad filename> What’s happening: git checkout alters files in the working directory to a state previously known to Git. You could provide a branch name or specific SHA you want to go back to or, by default, Git will assume you want to checkout HEAD , the last commit on the currently-checked-out branch. Keep in mind: any changes you “undo” this way are really gone. They were never committed, so Git can’t help us recover them later. Be sure you know what you’re throwing away here! (Maybe use git diff to confirm.) Reset “local” changes Scenario: You’ve made some commits locally (not yet pushed), but everything is terrible, you want to undo the last three commits—like they never happened. Undo with: git reset <last good SHA> or git reset --hard <last good SHA> What’s happening: git reset rewinds your repository’s history all the way back to the specified SHA. It’s as if those commits never happened. By default, git reset preserves the working directory. The commits are gone, but the contents are still on disk. This is the safest option, but often, you’ll want to “undo” the commits and the changes in one move—that’s what --hard does. Redo after undo “local” Scenario: You made some commits, did a git reset --hard to “undo” those changes (see above), and then realized: you want those changes back! Undo with: git reflog and git reset or git checkout What’s happening: git reflog is an amazing resource for recovering project history. You can recover almost anything—anything you’ve committed—via the reflog. You’re probably familiar with the git log command, which shows a list of commits. git reflog is similar, but instead shows a list of times when HEAD changed. Some caveats: HEAD changes only . HEAD changes when you switch branches, make commits with git commit and un-make commits with git reset , but HEAD does not change when you git checkout -- <bad filename> (from an earlier scenario—as mentioned before, those changes were never committed, so the reflog can’t help us recover those. git reflog doesn’t last forever. Git will periodically clean up objects which are “unreachable.” Don’t expect to find months-old commits lying around in the reflog forever. Your reflog is yours and yours alone. You can’t use git reflog to restore another developer’s un-pushed commits. So… how do you use the reflog to “redo” a previously “undone” commit or commits? It depends on what exactly you want to accomplish: If you want to restore the project’s history as it was at that moment in time use git reset --hard <SHA> If you want to recreate one or more files in your working directory as they were at that moment in time, without altering history use git checkout <SHA> -- <filename> If you want to replay exactly one of those commits into your repository use git cherry-pick <SHA> Once more, with branching Scenario: You made some commits, then realized you were checked out on master . You wish you could make those commits on a feature branch instead. Undo with: git branch feature , git reset --hard origin/master , and git checkout feature What’s happening: You may be used to creating new branches with git checkout -b <name> —it’s a popular short-cut for creating a new branch and checking it out right away—but you don’t want to switch branches just yet. Here, git branch feature creates a new branch called feature pointing at your most recent commit, but leaves you checked out to master . Next, git reset --hard rewinds master back to origin/master , before any of your new commits. Don’t worry, though, they are still available on feature . Finally, git checkout switches to the new feature branch, with all of your recent work intact. Branch in time saves nine Scenario: You started a new branch feature based on master , but master was pretty far behind origin/master . Now that master branch is in sync with origin/master , you wish commits on feature were starting now , instead of being so far behind. Undo with: git checkout feature and git rebase master What’s happening: You could have done this with git reset (no --hard , intentionally preserving changes on disk) then git checkout -b <new branch name> and then re-commit the changes, but that way, you’d lose the commit history. There’s a better way. git rebase master does a couple of things: First it locates the common ancestor between your currently-checked-out branch and master . Then it resets the currently-checked-out branch to that ancestor, holding all later commits in a temporary holding area. Then it advances the currently-checked-out-branch to the end of master and replays the commits from the holding area after master ‘s last commit. Mass undo/redo Scenario: You started this feature in one direction, but mid-way through, you realized another solution was better. You’ve got a dozen or so commits, but you only want some of them. You’d like the others to just disappear. Undo with: git rebase -i <earlier SHA> What’s happening: -i puts rebase in “interactive mode”. It starts off like the rebase discussed above, but before replaying any commits, it pauses and allows you to gently modify each commit as it’s replayed. rebase -i will open in your default text editor, with a list of commits being applied, like this: The first two columns are key: the first is the selected command for the commit identified by the SHA in the second column. By default, rebase -i assumes each commit is being applied, via the pick command. To drop a commit, just delete that line in your editor. If you no longer want the bad commits in your project, you can delete lines 1 and 3-4 above. If you want to preserve the contents of the commit but edit the commit message , you use the reword command. Just replace the word pick in the first column with the word reword (or just r ). It can be tempting to rewrite the commit message right now, but that won’t work— rebase -i ignores everything after the SHA column. The text after that is really just to help us remember what 0835fe2 is all about. When you’ve finished with rebase -i , you’ll be prompted for any new commit messages you need to write. If you want to combine two commits together, you can use the squash or fixup commands, like this: squash and fixup combine “up”—the commit with the “combine” command will be merged into the commit immediately before it. In this scenario, 0835fe2 and 6943e85 will be combined into one commit, then 38f5e4e and af67f82 will be combined together into another. When you select squash , Git will prompt us to give the new, combined commit a new commit message; fixup will give the new commit the message from the first commit in the list. Here, you know that af67f82 is an “ooops” commit, so you’ll just use the commit message from 38f5e4e as is, but you’ll write a new message for the new commit you get from combining 0835fe2 and 6943e85 . When you save and exit your editor, Git will apply your commits in order from top to bottom. You can alter the order commits apply by changing the order of commits before saving. If you’d wanted, you could have combined af67f82 with 0835fe2 by arranging things like this: Fix an earlier commit Scenario: You failed to include a file in an earlier commit, it’d be great if that earlier commit could somehow include the stuff you left out. You haven’t pushed, yet, but it wasn’t the most recent commit, so you can’t use commit --amend . Undo with: git commit --squash <SHA of the earlier commit> and git rebase --autosquash -i <even earlier SHA> What’s happening: git commit --squash will create a new commit with a commit message like squash! Earlier commit . (You could manually create a commit with a message like that, but commit --squash saves you some typing.) You can also use git commit --fixup if you don’t want to be prompted to write a new commit message for the combined commit. In this scenario, you’d probably use commit --fixup , since you just want to use the earlier commit’s commit message during rebase . rebase --autosquash -i will launch an interactive rebase editor, but the editor will open with any squash! and fixup! commits already paired to the commit target in the list of commits, like so: When using --squash and --fixup , you might not remember the SHA of the commit you want to fix—only that it was one or five commits ago. You might find using Git’s ^ and ~ operators especially handy. HEAD^ is one commit before HEAD . HEAD~4 is four commits before HEAD – or, altogether, five commits back. Stop tracking a tracked file Scenario: You accidentally added application.log to the repository, now every time you run the application, Git reports there are unstaged changes in application.log . You put *.log in the .gitignore file, but it’s still there—how do you tell git to to “undo” tracking changes in this file? Undo with: git rm --cached application.log What’s happening: While .gitignore prevents Git from tracking changes to files or even noticing the existence of files it’s never tracked before, once a file has been added and committed, Git will continue noticing changes in that file. Similarly, if you’ve used git add -f to “force”, or override, .gitignore , Git will keep tracking changes. You won’t have to use -f to add it in the future. If you want to remove that should-be-ignored file from Git’s tracking, git rm --cached will remove it from tracking but leave the file untouched on disk. Since it’s now being ignored, you won’t see that file in git status or accidentally commit changes from that file again. That’s how to undo anything with Git. To learn more about any of the Git commands used here, check out the relevant documentation: checkout commit rebase reflog reset revert rm Written by
Markdown
[Skip to content](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#start-of-content) [Skip to sidebar](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#sidebar) / [Blog](https://github.blog/) - [Changelog](https://github.blog/changelog/) - [Docs](https://docs.github.com/) - [Customer stories](https://github.com/customer-stories) [Try GitHub Copilot](https://github.com/features/copilot?utm_source=blog-tap-nav&utm_medium=blog&utm_campaign=universe25) [See what's new](https://github.com/events/universe/recap?utm_source=k2k-blog-tap-nav&utm_medium=blog&utm_campaign=universe25) - [AI & ML](https://github.blog/ai-and-ml/) - [AI & ML](https://github.blog/ai-and-ml/) Learn about artificial intelligence and machine learning across the GitHub ecosystem and the wider industry. - [Generative AI](https://github.blog/ai-and-ml/generative-ai/) Learn how to build with generative AI. - [GitHub Copilot](https://github.blog/ai-and-ml/github-copilot/) Change how you work with GitHub Copilot. - [LLMs](https://github.blog/ai-and-ml/llms/) Everything developers need to know about LLMs. - [Machine learning](https://github.blog/ai-and-ml/machine-learning/) Machine learning tips, tricks, and best practices. - ![](https://github.blog/wp-content/uploads/2024/06/AI-DarkMode-4.png?resize=800%2C425) [How AI code generation works](https://github.blog/ai-and-ml/generative-ai/how-ai-code-generation-works/) Explore the capabilities and benefits of AI code generation and how it can improve your developer experience. Learn more - [Developer skills](https://github.blog/developer-skills/) - [Developer skills](https://github.blog/developer-skills/) Resources for developers to grow in their skills and careers. - [Application development](https://github.blog/developer-skills/application-development/) Insights and best practices for building apps. - [Career growth](https://github.blog/developer-skills/career-growth/) Tips & tricks to grow as a professional developer. - [GitHub](https://github.blog/developer-skills/github/) Improve how you use GitHub at work. - [GitHub Education](https://github.blog/developer-skills/github-education/) Learn how to move into your first professional role. - [Programming languages & frameworks](https://github.blog/developer-skills/programming-languages-and-frameworks/) Stay current on what’s new (or new again). - ![](https://github.blog/wp-content/uploads/2024/05/Enterprise-DarkMode-3.png?resize=800%2C425) [Get started with GitHub documentation](https://docs.github.com/en/get-started) Learn how to start building, shipping, and maintaining software with GitHub. Learn more - [Engineering](https://github.blog/engineering/) - [Engineering](https://github.blog/engineering/) Get an inside look at how we’re building the home for all developers. - [Architecture & optimization](https://github.blog/engineering/architecture-optimization/) Discover how we deliver a performant and highly available experience across the GitHub platform. - [Engineering principles](https://github.blog/engineering/engineering-principles/) Explore best practices for building software at scale with a majority remote team. - [Infrastructure](https://github.blog/engineering/infrastructure/) Get a glimpse at the technology underlying the world’s leading AI-powered developer platform. - [Platform security](https://github.blog/engineering/platform-security/) Learn how we build security into everything we do across the developer lifecycle. - [User experience](https://github.blog/engineering/user-experience/) Find out what goes into making GitHub the home for all developers. - ![](https://github.blog/wp-content/uploads/2024/07/Screenshot-2024-07-23-at-8.42.45%E2%80%AFAM.png?resize=800%2C425) [How we use GitHub to be more productive, collaborative, and secure](https://github.blog/engineering/how-we-use-github-to-be-more-productive-collaborative-and-secure/) Our engineering and security teams do some incredible work. Let’s take a look at how we use GitHub to be more productive, build collaboratively, and shift security left. Learn more - [Enterprise software](https://github.blog/enterprise-software/) - [Enterprise software](https://github.blog/enterprise-software/) Explore how to write, build, and deploy enterprise software at scale. - [Automation](https://github.blog/enterprise-software/automation/) Automating your way to faster and more secure ships. - [CI/CD](https://github.blog/enterprise-software/ci-cd/) Guides on continuous integration and delivery. - [Collaboration](https://github.blog/enterprise-software/collaboration/) Tips, tools, and tricks to improve developer collaboration. - [DevOps](https://github.blog/enterprise-software/devops/) DevOps resources for enterprise engineering teams. - [DevSecOps](https://github.blog/enterprise-software/devsecops/) How to integrate security into the SDLC. - [Governance & compliance](https://github.blog/enterprise-software/governance-and-compliance/) Ensuring your builds stay clean. - ![](https://github.blog/wp-content/uploads/2024/07/Screenshot-2024-07-23-at-8.43.47%E2%80%AFAM.png?resize=800%2C425) [GitHub recognized as a Leader in the Gartner® Magic Quadrant™ for AI Code Assistants](https://github.com/resources/whitepapers/gartner-magic-quadrant-and-critical-capabilities-for-ai-code-assistants) Learn why Gartner positioned GitHub as a Leader for the second year in a row. Learn more - [News & insights](https://github.blog/news-insights/) - [News & insights](https://github.blog/news-insights/) Keep up with what’s new and notable from inside GitHub. - [Company news](https://github.blog/news-insights/company-news/) An inside look at news and product updates from GitHub. - [Product](https://github.blog/news-insights/product-news/) The latest on GitHub’s platform, products, and tools. - [Octoverse](https://github.blog/news-insights/octoverse/) Insights into the state of open source on GitHub. - [Policy](https://github.blog/news-insights/policy-news-and-insights/) The latest policy and regulatory changes in software. - [Research](https://github.blog/news-insights/research/) Data-driven insights around the developer ecosystem. - [The library](https://github.blog/news-insights/the-library/) Older news and updates from GitHub. - ![](https://github.blog/wp-content/uploads/2024/07/Screenshot-2024-07-23-at-8.44.23%E2%80%AFAM.png?resize=800%2C425) [Unlocking the power of unstructured data with RAG](https://github.blog/ai-and-ml/llms/unlocking-the-power-of-unstructured-data-with-rag/) Learn how to use retrieval-augmented generation (RAG) to capture more insights. Learn more - [Open Source](https://github.blog/open-source/) - [Open Source](https://github.blog/open-source/) Everything open source on GitHub. - [Git](https://github.blog/open-source/git/) The latest Git updates. - [Maintainers](https://github.blog/open-source/maintainers/) Spotlighting open source maintainers. - [Social impact](https://github.blog/open-source/social-impact/) How open source is driving positive change. - [Gaming](https://github.blog/open-source/gaming/) Explore open source games on GitHub. - ![](https://github.blog/wp-content/uploads/2024/07/Screenshot-2024-07-23-at-8.46.23%E2%80%AFAM.png?resize=800%2C425) [An introduction to innersource](https://resources.github.com/software-development/innersource/) Organizations worldwide are incorporating open source methodologies into the way they build and ship their own software. Learn more - [Security](https://github.blog/security/) - [Security](https://github.blog/security/) Stay up to date on everything security. - [Application security](https://github.blog/security/application-security/) Application security, explained. - [Supply chain security](https://github.blog/security/supply-chain-security/) Demystifying supply chain security. - [Vulnerability research](https://github.blog/security/vulnerability-research/) Updates from the GitHub Security Lab. - [Web application security](https://github.blog/security/web-application-security/) Helpful tips on securing web applications. - ![](https://github.blog/wp-content/uploads/2024/07/Screenshot-2024-07-23-at-8.47.04%E2%80%AFAM.png?resize=800%2C425) [The enterprise guide to AI-powered DevSecOps](https://resources.github.com/security/the-enterprise-guide-to-ai-powered-devsecops/) Learn about core challenges in DevSecOps, and how you can start addressing them with AI and automation. Learn more ## Categories - [AI & ML](https://github.blog/ai-and-ml/) - Back [AI & ML](https://github.blog/ai-and-ml/) Learn about artificial intelligence and machine learning across the GitHub ecosystem and the wider industry. - [Generative AI](https://github.blog/ai-and-ml/generative-ai/) Learn how to build with generative AI. - [GitHub Copilot](https://github.blog/ai-and-ml/github-copilot/) Change how you work with GitHub Copilot. - [LLMs](https://github.blog/ai-and-ml/llms/) Everything developers need to know about LLMs. - [Machine learning](https://github.blog/ai-and-ml/machine-learning/) Machine learning tips, tricks, and best practices. - [How AI code generation works](https://github.blog/ai-and-ml/generative-ai/how-ai-code-generation-works/) Explore the capabilities and benefits of AI code generation and how it can improve your developer experience. [Learn more](https://github.blog/ai-and-ml/generative-ai/how-ai-code-generation-works/) - [Developer skills](https://github.blog/developer-skills/) - Back [Developer skills](https://github.blog/developer-skills/) Resources for developers to grow in their skills and careers. - [Application development](https://github.blog/developer-skills/application-development/) Insights and best practices for building apps. - [Career growth](https://github.blog/developer-skills/career-growth/) Tips & tricks to grow as a professional developer. - [GitHub](https://github.blog/developer-skills/github/) Improve how you use GitHub at work. - [GitHub Education](https://github.blog/developer-skills/github-education/) Learn how to move into your first professional role. - [Programming languages & frameworks](https://github.blog/developer-skills/programming-languages-and-frameworks/) Stay current on what’s new (or new again). - [Get started with GitHub documentation](https://docs.github.com/en/get-started) Learn how to start building, shipping, and maintaining software with GitHub. [Learn more](https://docs.github.com/en/get-started) - [Engineering](https://github.blog/engineering/) - Back [Engineering](https://github.blog/engineering/) Get an inside look at how we’re building the home for all developers. - [Architecture & optimization](https://github.blog/engineering/architecture-optimization/) Discover how we deliver a performant and highly available experience across the GitHub platform. - [Engineering principles](https://github.blog/engineering/engineering-principles/) Explore best practices for building software at scale with a majority remote team. - [Infrastructure](https://github.blog/engineering/infrastructure/) Get a glimpse at the technology underlying the world’s leading AI-powered developer platform. - [Platform security](https://github.blog/engineering/platform-security/) Learn how we build security into everything we do across the developer lifecycle. - [User experience](https://github.blog/engineering/user-experience/) Find out what goes into making GitHub the home for all developers. - [How we use GitHub to be more productive, collaborative, and secure](https://github.blog/engineering/how-we-use-github-to-be-more-productive-collaborative-and-secure/) Our engineering and security teams do some incredible work. Let’s take a look at how we use GitHub to be more productive, build collaboratively, and shift security left. [Learn more](https://github.blog/engineering/how-we-use-github-to-be-more-productive-collaborative-and-secure/) - [Enterprise software](https://github.blog/enterprise-software/) - Back [Enterprise software](https://github.blog/enterprise-software/) Explore how to write, build, and deploy enterprise software at scale. - [Automation](https://github.blog/enterprise-software/automation/) Automating your way to faster and more secure ships. - [CI/CD](https://github.blog/enterprise-software/ci-cd/) Guides on continuous integration and delivery. - [Collaboration](https://github.blog/enterprise-software/collaboration/) Tips, tools, and tricks to improve developer collaboration. - [DevOps](https://github.blog/enterprise-software/devops/) DevOps resources for enterprise engineering teams. - [DevSecOps](https://github.blog/enterprise-software/devsecops/) How to integrate security into the SDLC. - [Governance & compliance](https://github.blog/enterprise-software/governance-and-compliance/) Ensuring your builds stay clean. - [GitHub recognized as a Leader in the Gartner® Magic Quadrant™ for AI Code Assistants](https://github.com/resources/whitepapers/gartner-magic-quadrant-and-critical-capabilities-for-ai-code-assistants) Learn why Gartner positioned GitHub as a Leader for the second year in a row. [Learn more](https://github.com/resources/whitepapers/gartner-magic-quadrant-and-critical-capabilities-for-ai-code-assistants) - [News & insights](https://github.blog/news-insights/) - Back [News & insights](https://github.blog/news-insights/) Keep up with what’s new and notable from inside GitHub. - [Company news](https://github.blog/news-insights/company-news/) An inside look at news and product updates from GitHub. - [Product](https://github.blog/news-insights/product-news/) The latest on GitHub’s platform, products, and tools. - [Octoverse](https://github.blog/news-insights/octoverse/) Insights into the state of open source on GitHub. - [Policy](https://github.blog/news-insights/policy-news-and-insights/) The latest policy and regulatory changes in software. - [Research](https://github.blog/news-insights/research/) Data-driven insights around the developer ecosystem. - [The library](https://github.blog/news-insights/the-library/) Older news and updates from GitHub. - [Unlocking the power of unstructured data with RAG](https://github.blog/ai-and-ml/llms/unlocking-the-power-of-unstructured-data-with-rag/) Learn how to use retrieval-augmented generation (RAG) to capture more insights. [Learn more](https://github.blog/ai-and-ml/llms/unlocking-the-power-of-unstructured-data-with-rag/) - [Open Source](https://github.blog/open-source/) - Back [Open Source](https://github.blog/open-source/) Everything open source on GitHub. - [Git](https://github.blog/open-source/git/) The latest Git updates. - [Maintainers](https://github.blog/open-source/maintainers/) Spotlighting open source maintainers. - [Social impact](https://github.blog/open-source/social-impact/) How open source is driving positive change. - [Gaming](https://github.blog/open-source/gaming/) Explore open source games on GitHub. - [An introduction to innersource](https://resources.github.com/software-development/innersource/) Organizations worldwide are incorporating open source methodologies into the way they build and ship their own software. [Learn more](https://resources.github.com/software-development/innersource/) - [Security](https://github.blog/security/) - Back [Security](https://github.blog/security/) Stay up to date on everything security. - [Application security](https://github.blog/security/application-security/) Application security, explained. - [Supply chain security](https://github.blog/security/supply-chain-security/) Demystifying supply chain security. - [Vulnerability research](https://github.blog/security/vulnerability-research/) Updates from the GitHub Security Lab. - [Web application security](https://github.blog/security/web-application-security/) Helpful tips on securing web applications. - [The enterprise guide to AI-powered DevSecOps](https://resources.github.com/security/the-enterprise-guide-to-ai-powered-devsecops/) Learn about core challenges in DevSecOps, and how you can start addressing them with AI and automation. [Learn more](https://resources.github.com/security/the-enterprise-guide-to-ai-powered-devsecops/) - [Changelog](https://github.blog/changelog/) - [Docs](https://docs.github.com/) - [Customer stories](https://github.com/customer-stories) [See what's new](https://github.com/events/universe/recap?utm_source=k2k-blog-tap-nav&utm_medium=blog&utm_campaign=universe25) [Try GitHub Copilot](https://github.com/features/copilot?utm_source=blog-tap-nav&utm_medium=blog&utm_campaign=universe25) [Home](https://github.blog/) / [Open Source](https://github.blog/open-source/) / [Git](https://github.blog/open-source/git/) # How to undo (almost) anything with Git One of the most useful features of any version control system is the ability to “undo” your mistakes. In Git, “undo” can mean many slightly different things. ![](https://github.blog/wp-content/uploads/2019/03/community-twitter.png?resize=1201%2C630) [Joshua Wehner](https://github.blog/author/jaw6/ "Posts by Joshua Wehner")·[@jaw6](https://github.com/jaw6) June 8, 2015 \| Updated July 23, 2024 \| 9 minutes - Share: One of the most useful features of any version control system is the ability to “undo” your mistakes. In Git, “undo” can mean many slightly different things. When you make a new commit, Git stores a snapshot of your repository at that specific moment in time; later, you can use Git to go back to an earlier version of your project. In this post, I’m going to take a look at some common scenarios where you might want to “undo” a change you’ve made and the best way to do it using Git. ## [Undo a “public” change](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#undo-a-public-change) **Scenario:** You just ran `git push`, sending your changes to GitHub, now you realize there’s a problem with one of those commits. You’d like to undo that commit. **Undo with:** `git revert <SHA>` **What’s happening:** `git revert` will create a new commit that’s the opposite (or inverse) of the given SHA. If the old commit is “matter”, the new commit is “anti-matter”—anything removed in the old commit will be added in the new commit and anything added in the old commit will be removed in the new commit. This is Git’s safest, most basic “undo” scenario, because it doesn’t *alter* history—so you can now `git push` the new “inverse” commit to undo your mistaken commit. ## [Fix the last commit message](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#fix-the-last-commit-message) **Scenario:** You just typo’d the last commit message, you did `git commit -m "Fxies bug #42"` but before `git push` you realized that really should say “Fixes bug \#42”. **Undo with:** `git commit --amend` or `git commit --amend -m "Fixes bug #42"` **What’s happening:** `git commit --amend` will update and replace the most recent commit with a new commit that combines any staged changes with the contents of the previous commit. With nothing currently staged, this just rewrites the previous commit message. ## [Undo “local” changes](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#undo-local-changes) **Scenario:** The cat walked across the keyboard and somehow saved the changes, then crashed the editor. You haven’t committed those changes, though. You want to undo everything in that file—just go back to the way it looked in the last commit. **Undo with:** `git checkout -- <bad filename>` **What’s happening:** `git checkout` alters files in the working directory to a state previously known to Git. You could provide a branch name or specific SHA you want to go back to or, by default, Git will assume you want to checkout `HEAD`, the last commit on the currently-checked-out branch. Keep in mind: any changes you “undo” this way are *really* gone. They were never committed, so Git can’t help us recover them later. Be sure you know what you’re throwing away here! (Maybe use `git diff` to confirm.) ## [Reset “local” changes](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#reset-local-changes) **Scenario:** You’ve made some commits locally (not yet pushed), but everything is terrible, you want to undo the last three commits—like they never happened. **Undo with:** `git reset <last good SHA>` or `git reset --hard <last good SHA>` **What’s happening:** `git reset` rewinds your repository’s history all the way back to the specified SHA. It’s as if those commits never happened. By default, `git reset` preserves the working directory. The commits are gone, but the *contents* are still on disk. This is the safest option, but often, you’ll want to “undo” the commits *and* the changes in one move—that’s what `--hard` does. ## [Redo after undo “local”](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#redo-after-undo-local) **Scenario:** You made some commits, did a `git reset --hard` to “undo” those changes (see above), and *then* realized: you want those changes back\! **Undo with:** `git reflog` and `git reset` or `git checkout` **What’s happening:** `git reflog` is an amazing resource for recovering project history. You can recover *almost* anything—anything you’ve committed—via the reflog. You’re probably familiar with the `git log` command, which shows a list of commits. `git reflog` is similar, but instead shows a list of times when `HEAD` changed. Some caveats: - `HEAD` changes *only*.`HEAD` changes when you switch branches, make commits with `git commit` and un-make commits with `git reset`, but `HEAD` does *not* change when you `git checkout -- <bad filename>` (from an earlier scenario—as mentioned before, those changes were never committed, so the reflog can’t help us recover those. - `git reflog` doesn’t last forever. Git will periodically clean up objects which are “unreachable.” Don’t expect to find months-old commits lying around in the reflog forever. - Your `reflog` is yours and yours alone. You can’t use `git reflog` to restore another developer’s un-pushed commits. ![reflog](https://github.blog/wp-content/uploads/2015/06/f6b9f054-d891-11e4-8c53-838eff9f40ae.png?resize=1429%2C644) So… how do you use the reflog to “redo” a previously “undone” commit or commits? It depends on what exactly you want to accomplish: - If you want to restore the project’s history as it was at that moment in time use `git reset --hard <SHA>` - If you want to recreate one or more files in your working directory as they were at that moment in time, without altering history use `git checkout <SHA> -- <filename>` - If you want to replay *exactly one* of those commits into your repository use `git cherry-pick <SHA>` ## [Once more, with branching](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#once-more-with-branching) **Scenario:** You made some commits, then realized you were checked out on `master`. You wish you could make those commits on a feature branch instead. **Undo with:** `git branch feature`, `git reset --hard origin/master`, and `git checkout feature` **What’s happening:** You may be used to creating new branches with `git checkout -b <name>`—it’s a popular short-cut for creating a new branch and checking it out right away—but you don’t want to switch branches just yet. Here, `git branch feature` creates a new branch called `feature` pointing at your most recent commit, but leaves you checked out to `master`. Next, `git reset --hard` rewinds `master` back to `origin/master`, before any of your new commits. Don’t worry, though, they are still available on `feature`. Finally, `git checkout` switches to the new `feature` branch, with all of your recent work intact. ## [Branch in time saves nine](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#branch-in-time-saves-nine) **Scenario:** You started a new branch `feature` based on `master`, but `master` was pretty far behind `origin/master`. Now that `master` branch is in sync with `origin/master`, you wish commits on `feature` were starting *now*, instead of being so far behind. **Undo with:** `git checkout feature` and `git rebase master` **What’s happening:** You could have done this with `git reset` (no `--hard`, intentionally preserving changes on disk) then `git checkout -b <new branch name>` and then re-commit the changes, but that way, you’d lose the commit history. There’s a better way. `git rebase master` does a couple of things: - First it locates the common ancestor between your currently-checked-out branch and `master`. - Then it resets the currently-checked-out branch to that ancestor, holding all later commits in a temporary holding area. - Then it advances the currently-checked-out-branch to the end of `master` and replays the commits from the holding area *after* `master`‘s last commit. ## [Mass undo/redo](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#mass-undo-redo) **Scenario:** You started this feature in one direction, but mid-way through, you realized another solution was better. You’ve got a dozen or so commits, but you only want some of them. You’d like the others to just disappear. **Undo with:** `git rebase -i <earlier SHA>` **What’s happening:** `-i` puts `rebase` in “interactive mode”. It starts off like the rebase discussed above, but before replaying any commits, it pauses and allows you to gently modify each commit as it’s replayed. `rebase -i` will open in your default text editor, with a list of commits being applied, like this: ![rebase-interactive1](https://github.blog/wp-content/uploads/2015/06/f6b1ab88-d891-11e4-97c1-e0630ac74e74.png?resize=1459%2C495) The first two columns are key: the first is the selected command for the commit identified by the SHA in the second column. By default, `rebase -i` assumes each commit is being applied, via the `pick` command. To drop a commit, just delete that line in your editor. If you no longer want the bad commits in your project, you can delete lines 1 and 3-4 above. If you want to preserve the *contents* of the commit but edit the commit *message*, you use the `reword` command. Just replace the word `pick` in the first column with the word `reword` (or just `r`). It can be tempting to rewrite the commit message right now, but that won’t work—`rebase -i` ignores everything after the SHA column. The text after that is really just to help us remember what `0835fe2` is all about. When you’ve finished with `rebase -i`, you’ll be prompted for any new commit messages you need to write. If you want to combine two commits together, you can use the `squash` or `fixup` commands, like this: ![rebase-interactive2](https://github.blog/wp-content/uploads/2015/06/f6b605ca-d891-11e4-98cf-d567ca9f4edc.png?resize=1449%2C339) `squash` and `fixup` combine “up”—the commit with the “combine” command will be merged into the commit immediately before it. In this scenario, `0835fe2` and `6943e85` will be combined into one commit, then `38f5e4e` and `af67f82` will be combined together into another. When you select `squash`, Git will prompt us to give the new, combined commit a new commit message; `fixup` will give the new commit the message from the first commit in the list. Here, you know that `af67f82` is an “ooops” commit, so you’ll just use the commit message from `38f5e4e` as is, but you’ll write a new message for the new commit you get from combining `0835fe2` and `6943e85`. When you save and exit your editor, Git will apply your commits in order from top to bottom. You can alter the order commits apply by changing the order of commits before saving. If you’d wanted, you could have combined `af67f82` with `0835fe2` by arranging things like this: ![rebase-interactive3](https://github.blog/wp-content/uploads/2015/06/f6b4a9d2-d891-11e4-9ac9-10039c031d06.png?resize=1445%2C326) ## [Fix an earlier commit](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#fix-an-earlier-commit) **Scenario:** You failed to include a file in an earlier commit, it’d be great if that earlier commit could somehow include the stuff you left out. You haven’t pushed, yet, but it wasn’t the most recent commit, so you can’t use `commit --amend`. **Undo with:** `git commit --squash <SHA of the earlier commit>` and `git rebase --autosquash -i <even earlier SHA>` **What’s happening:** `git commit --squash` will create a new commit with a commit message like `squash! Earlier commit`. (You could manually create a commit with a message like that, but `commit --squash` saves you some typing.) You can also use `git commit --fixup` if you don’t want to be prompted to write a new commit message for the combined commit. In this scenario, you’d probably use `commit --fixup`, since you just want to use the earlier commit’s commit message during `rebase`. `rebase --autosquash -i` will launch an interactive `rebase` editor, but the editor will open with any `squash!` and `fixup!` commits already paired to the commit target in the list of commits, like so: ![rebase-autosquash](https://github.blog/wp-content/uploads/2015/06/f6a7a1d8-d891-11e4-8784-c32262ff54da.png?resize=1446%2C294) When using `--squash` and `--fixup`, you might not remember the SHA of the commit you want to fix—only that it was one or five commits ago. You might find using Git’s `^` and `~` operators especially handy. `HEAD^` is one commit before `HEAD`. `HEAD~4` is four commits before `HEAD` – or, altogether, five commits back. ## [Stop tracking a tracked file](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#stop-tracking-a-tracked-file) **Scenario:** You accidentally added `application.log` to the repository, now every time you run the application, Git reports there are unstaged changes in `application.log`. You put `*.log` in the `.gitignore` file, but it’s still there—how do you tell git to to “undo” tracking changes in this file? **Undo with:** `git rm --cached application.log` **What’s happening:** While `.gitignore` prevents Git from tracking changes to files or even noticing the existence of files it’s never tracked before, once a file has been added and committed, Git will continue noticing changes in that file. Similarly, if you’ve used `git add -f` to “force”, or override, `.gitignore`, Git will keep tracking changes. You won’t have to use `-f` to add it in the future. If you want to remove that should-be-ignored file from Git’s tracking, `git rm --cached` will remove it from tracking but leave the file untouched on disk. Since it’s now being ignored, you won’t see that file in `git status` or accidentally commit changes from that file again. *** That’s how to undo anything with Git. To learn more about any of the Git commands used here, check out the relevant documentation: - [checkout](http://git-scm.com/docs/git-checkout) - [commit](http://git-scm.com/docs/git-commit) - [rebase](http://git-scm.com/docs/git-rebase) - [reflog](http://git-scm.com/docs/git-reflog) - [reset](http://git-scm.com/docs/git-reset) - [revert](http://git-scm.com/docs/git-revert) - [rm](http://git-scm.com/docs/git-rm) *** ## Tags: - [Git](https://github.blog/tag/git/) ## Written by ![Joshua Wehner](https://avatars0.githubusercontent.com/u/2077?v=4&s=200) ### [Joshua Wehner](https://github.blog/author/jaw6/) [@jaw6](https://github.com/jaw6) - [Git](https://github.blog/tag/git/) ## More on [Git](https://github.blog/tag/git/) ### [Highlights from Git 2.52](https://github.blog/open-source/git/highlights-from-git-2-52/) The open source Git project just released Git 2.52. Here is GitHub’s look at some of the most interesting features and changes introduced since last time. [Taylor Blau](https://github.blog/author/ttaylorr/ "Posts by Taylor Blau") ### [20 Years of Git, 2 days at GitHub HQ: Git Merge 2025 highlights 🎉](https://github.blog/open-source/git/20-years-of-git-2-days-at-github-hq-git-merge-2025-highlights/) Git Merge 2025 celebrated 20 years of Git with talks, collaboration, and community. Catch the highlights and recordings. [Lee Reilly](https://github.blog/author/leereilly/ "Posts by Lee Reilly") ## Related posts ![](https://github.blog/wp-content/uploads/2025/11/GithubStockIllos_Hiring_final-copy.jpg?resize=400%2C212) [Maintainers](https://github.blog/open-source/maintainers/) ### [Rethinking open source mentorship in the AI era](https://github.blog/open-source/maintainers/rethinking-open-source-mentorship-in-the-ai-era/) As contribution volume grows, mentorship signals are harder to read. The 3 Cs framework helps maintainers mentor more strategically… without burning out. [Abigail Cabunoc Mayes](https://github.blog/author/abbycabs/ "Posts by Abigail Cabunoc Mayes") ![Joining forces to strengthen open source security. 280,000+ maintainers: receive free Copilot Pro, advanced security, and resources so maintainers can ship and stay secure.](https://github.blog/wp-content/uploads/2026/03/AlphaOmegaBlog_Header_01-4.png?resize=400%2C212) [Maintainers](https://github.blog/open-source/maintainers/) ### [Investing in the people shaping open source and securing the future together](https://github.blog/security/supply-chain-security/investing-in-the-people-shaping-open-source-and-securing-the-future-together/) See how GitHub is investing in open source security funding maintainers, partnering with Alpha-Omega, and expanding access to help reduce burden and strengthen software supply chains. [Kevin Crosby](https://github.blog/author/kevincrosby/ "Posts by Kevin Crosby") ![An abstract illustration of connected blocks surrounding a central shield with a checkmark representing secure and verified systems.](https://github.blog/wp-content/uploads/2026/01/generic-github-security-logo.png?resize=400%2C212) [AI & ML](https://github.blog/ai-and-ml/) ### [How to scan for vulnerabilities with GitHub Security Lab’s open source AI-powered framework](https://github.blog/security/how-to-scan-for-vulnerabilities-with-github-security-labs-open-source-ai-powered-framework/) GitHub Security Lab Taskflow Agent is very effective at finding Auth Bypasses, IDORs, Token Leaks, and other high-impact vulnerabilities. [Man Yue Mo](https://github.blog/author/mymo/ "Posts by Man Yue Mo") & [Peter Stöckli](https://github.blog/author/stockli/ "Posts by Peter Stöckli") ## Explore more from GitHub ![Docs](https://github.blog/wp-content/uploads/2024/07/Icon-Circle.svg) ### Docs Everything you need to master GitHub, all in one place. [Go to Docs](https://docs.github.com/) ![GitHub](https://github.blog/wp-content/uploads/2024/07/recirculation-github-icon.svg) ### GitHub Build what’s next on GitHub, the place for anyone from anywhere to build anything. [Start building](https://github.com/) ![GitHub Copilot](https://github.blog/wp-content/uploads/2022/05/Copilot_Blog_Icon-1.svg) ### GitHub Copilot Don’t fly solo. Try 30 days for free. [Learn more](https://github.blog/ai-and-ml/github-copilot/) ![Enterprise content](https://github.blog/wp-content/uploads/2022/05/careers.svg) ### Enterprise content Executive insights, curated just for you [Get started](https://github.com/solutions/executive-insights) ## We do newsletters, too Discover tips, technical guides, and best practices in our biweekly newsletter just for devs. Your email address ## Site-wide Links ### Product - [Features](https://github.com/features) - [Security](https://github.com/security) - [Enterprise](https://github.com/enterprise) - [Customer Stories](https://github.com/customer-stories?type=enterprise) - [Pricing](https://github.com/pricing) - [Resources](https://resources.github.com/) ### Platform - [Developer API](https://developer.github.com/) - [Partners](https://partner.github.com/) - [Atom](https://atom.io/) - [Electron](https://www.electronjs.org/) - [GitHub Desktop](https://desktop.github.com/) ### Support - [Docs](https://docs.github.com/) - [Community Forum](https://github.community/) - [Training](https://services.github.com/) - [Status](https://www.githubstatus.com/) - [Contact](https://support.github.com/) ### Company - [About](https://github.com/about) - [Blog](https://github.blog/) - [Careers](https://github.com/about/careers) - [Press](https://github.com/about/press) - [Shop](https://shop.github.com/) - © 2026 GitHub, Inc. - [Terms](https://docs.github.com/en/github/site-policy/github-terms-of-service) - [Privacy](https://docs.github.com/en/github/site-policy/github-privacy-statement) - Manage Cookies - Do not share my personal information - [GitHub on LinkedIn](https://www.linkedin.com/company/github) - [GitHub on Instagram](https://www.instagram.com/github/) - [GitHub on YouTube](https://www.youtube.com/github) - [GitHub on X](https://twitter.com/github) - [GitHub on TikTok](https://www.tiktok.com/@github) - [GitHub on Twitch](https://www.twitch.tv/github) - [GitHub’s organization on GitHub](https://github.com/github)
Readable Markdown
One of the most useful features of any version control system is the ability to “undo” your mistakes. In Git, “undo” can mean many slightly different things. When you make a new commit, Git stores a snapshot of your repository at that specific moment in time; later, you can use Git to go back to an earlier version of your project. In this post, I’m going to take a look at some common scenarios where you might want to “undo” a change you’ve made and the best way to do it using Git. ## [Undo a “public” change](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#undo-a-public-change) **Scenario:** You just ran `git push`, sending your changes to GitHub, now you realize there’s a problem with one of those commits. You’d like to undo that commit. **Undo with:** `git revert <SHA>` **What’s happening:** `git revert` will create a new commit that’s the opposite (or inverse) of the given SHA. If the old commit is “matter”, the new commit is “anti-matter”—anything removed in the old commit will be added in the new commit and anything added in the old commit will be removed in the new commit. This is Git’s safest, most basic “undo” scenario, because it doesn’t *alter* history—so you can now `git push` the new “inverse” commit to undo your mistaken commit. ## [Fix the last commit message](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#fix-the-last-commit-message) **Scenario:** You just typo’d the last commit message, you did `git commit -m "Fxies bug #42"` but before `git push` you realized that really should say “Fixes bug \#42”. **Undo with:** `git commit --amend` or `git commit --amend -m "Fixes bug #42"` **What’s happening:** `git commit --amend` will update and replace the most recent commit with a new commit that combines any staged changes with the contents of the previous commit. With nothing currently staged, this just rewrites the previous commit message. ## [Undo “local” changes](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#undo-local-changes) **Scenario:** The cat walked across the keyboard and somehow saved the changes, then crashed the editor. You haven’t committed those changes, though. You want to undo everything in that file—just go back to the way it looked in the last commit. **Undo with:** `git checkout -- <bad filename>` **What’s happening:** `git checkout` alters files in the working directory to a state previously known to Git. You could provide a branch name or specific SHA you want to go back to or, by default, Git will assume you want to checkout `HEAD`, the last commit on the currently-checked-out branch. Keep in mind: any changes you “undo” this way are *really* gone. They were never committed, so Git can’t help us recover them later. Be sure you know what you’re throwing away here! (Maybe use `git diff` to confirm.) ## [Reset “local” changes](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#reset-local-changes) **Scenario:** You’ve made some commits locally (not yet pushed), but everything is terrible, you want to undo the last three commits—like they never happened. **Undo with:** `git reset <last good SHA>` or `git reset --hard <last good SHA>` **What’s happening:** `git reset` rewinds your repository’s history all the way back to the specified SHA. It’s as if those commits never happened. By default, `git reset` preserves the working directory. The commits are gone, but the *contents* are still on disk. This is the safest option, but often, you’ll want to “undo” the commits *and* the changes in one move—that’s what `--hard` does. ## [Redo after undo “local”](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#redo-after-undo-local) **Scenario:** You made some commits, did a `git reset --hard` to “undo” those changes (see above), and *then* realized: you want those changes back\! **Undo with:** `git reflog` and `git reset` or `git checkout` **What’s happening:** `git reflog` is an amazing resource for recovering project history. You can recover *almost* anything—anything you’ve committed—via the reflog. You’re probably familiar with the `git log` command, which shows a list of commits. `git reflog` is similar, but instead shows a list of times when `HEAD` changed. Some caveats: - `HEAD` changes *only*.`HEAD` changes when you switch branches, make commits with `git commit` and un-make commits with `git reset`, but `HEAD` does *not* change when you `git checkout -- <bad filename>` (from an earlier scenario—as mentioned before, those changes were never committed, so the reflog can’t help us recover those. - `git reflog` doesn’t last forever. Git will periodically clean up objects which are “unreachable.” Don’t expect to find months-old commits lying around in the reflog forever. - Your `reflog` is yours and yours alone. You can’t use `git reflog` to restore another developer’s un-pushed commits. ![reflog](https://github.blog/wp-content/uploads/2015/06/f6b9f054-d891-11e4-8c53-838eff9f40ae.png?resize=1429%2C644) So… how do you use the reflog to “redo” a previously “undone” commit or commits? It depends on what exactly you want to accomplish: - If you want to restore the project’s history as it was at that moment in time use `git reset --hard <SHA>` - If you want to recreate one or more files in your working directory as they were at that moment in time, without altering history use `git checkout <SHA> -- <filename>` - If you want to replay *exactly one* of those commits into your repository use `git cherry-pick <SHA>` ## [Once more, with branching](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#once-more-with-branching) **Scenario:** You made some commits, then realized you were checked out on `master`. You wish you could make those commits on a feature branch instead. **Undo with:** `git branch feature`, `git reset --hard origin/master`, and `git checkout feature` **What’s happening:** You may be used to creating new branches with `git checkout -b <name>`—it’s a popular short-cut for creating a new branch and checking it out right away—but you don’t want to switch branches just yet. Here, `git branch feature` creates a new branch called `feature` pointing at your most recent commit, but leaves you checked out to `master`. Next, `git reset --hard` rewinds `master` back to `origin/master`, before any of your new commits. Don’t worry, though, they are still available on `feature`. Finally, `git checkout` switches to the new `feature` branch, with all of your recent work intact. ## [Branch in time saves nine](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#branch-in-time-saves-nine) **Scenario:** You started a new branch `feature` based on `master`, but `master` was pretty far behind `origin/master`. Now that `master` branch is in sync with `origin/master`, you wish commits on `feature` were starting *now*, instead of being so far behind. **Undo with:** `git checkout feature` and `git rebase master` **What’s happening:** You could have done this with `git reset` (no `--hard`, intentionally preserving changes on disk) then `git checkout -b <new branch name>` and then re-commit the changes, but that way, you’d lose the commit history. There’s a better way. `git rebase master` does a couple of things: - First it locates the common ancestor between your currently-checked-out branch and `master`. - Then it resets the currently-checked-out branch to that ancestor, holding all later commits in a temporary holding area. - Then it advances the currently-checked-out-branch to the end of `master` and replays the commits from the holding area *after* `master`‘s last commit. ## [Mass undo/redo](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#mass-undo-redo) **Scenario:** You started this feature in one direction, but mid-way through, you realized another solution was better. You’ve got a dozen or so commits, but you only want some of them. You’d like the others to just disappear. **Undo with:** `git rebase -i <earlier SHA>` **What’s happening:** `-i` puts `rebase` in “interactive mode”. It starts off like the rebase discussed above, but before replaying any commits, it pauses and allows you to gently modify each commit as it’s replayed. `rebase -i` will open in your default text editor, with a list of commits being applied, like this: ![rebase-interactive1](https://github.blog/wp-content/uploads/2015/06/f6b1ab88-d891-11e4-97c1-e0630ac74e74.png?resize=1459%2C495) The first two columns are key: the first is the selected command for the commit identified by the SHA in the second column. By default, `rebase -i` assumes each commit is being applied, via the `pick` command. To drop a commit, just delete that line in your editor. If you no longer want the bad commits in your project, you can delete lines 1 and 3-4 above. If you want to preserve the *contents* of the commit but edit the commit *message*, you use the `reword` command. Just replace the word `pick` in the first column with the word `reword` (or just `r`). It can be tempting to rewrite the commit message right now, but that won’t work—`rebase -i` ignores everything after the SHA column. The text after that is really just to help us remember what `0835fe2` is all about. When you’ve finished with `rebase -i`, you’ll be prompted for any new commit messages you need to write. If you want to combine two commits together, you can use the `squash` or `fixup` commands, like this: ![rebase-interactive2](https://github.blog/wp-content/uploads/2015/06/f6b605ca-d891-11e4-98cf-d567ca9f4edc.png?resize=1449%2C339) `squash` and `fixup` combine “up”—the commit with the “combine” command will be merged into the commit immediately before it. In this scenario, `0835fe2` and `6943e85` will be combined into one commit, then `38f5e4e` and `af67f82` will be combined together into another. When you select `squash`, Git will prompt us to give the new, combined commit a new commit message; `fixup` will give the new commit the message from the first commit in the list. Here, you know that `af67f82` is an “ooops” commit, so you’ll just use the commit message from `38f5e4e` as is, but you’ll write a new message for the new commit you get from combining `0835fe2` and `6943e85`. When you save and exit your editor, Git will apply your commits in order from top to bottom. You can alter the order commits apply by changing the order of commits before saving. If you’d wanted, you could have combined `af67f82` with `0835fe2` by arranging things like this: ![rebase-interactive3](https://github.blog/wp-content/uploads/2015/06/f6b4a9d2-d891-11e4-9ac9-10039c031d06.png?resize=1445%2C326) ## [Fix an earlier commit](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#fix-an-earlier-commit) **Scenario:** You failed to include a file in an earlier commit, it’d be great if that earlier commit could somehow include the stuff you left out. You haven’t pushed, yet, but it wasn’t the most recent commit, so you can’t use `commit --amend`. **Undo with:** `git commit --squash <SHA of the earlier commit>` and `git rebase --autosquash -i <even earlier SHA>` **What’s happening:** `git commit --squash` will create a new commit with a commit message like `squash! Earlier commit`. (You could manually create a commit with a message like that, but `commit --squash` saves you some typing.) You can also use `git commit --fixup` if you don’t want to be prompted to write a new commit message for the combined commit. In this scenario, you’d probably use `commit --fixup`, since you just want to use the earlier commit’s commit message during `rebase`. `rebase --autosquash -i` will launch an interactive `rebase` editor, but the editor will open with any `squash!` and `fixup!` commits already paired to the commit target in the list of commits, like so: ![rebase-autosquash](https://github.blog/wp-content/uploads/2015/06/f6a7a1d8-d891-11e4-8784-c32262ff54da.png?resize=1446%2C294) When using `--squash` and `--fixup`, you might not remember the SHA of the commit you want to fix—only that it was one or five commits ago. You might find using Git’s `^` and `~` operators especially handy. `HEAD^` is one commit before `HEAD`. `HEAD~4` is four commits before `HEAD` – or, altogether, five commits back. ## [Stop tracking a tracked file](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/#stop-tracking-a-tracked-file) **Scenario:** You accidentally added `application.log` to the repository, now every time you run the application, Git reports there are unstaged changes in `application.log`. You put `*.log` in the `.gitignore` file, but it’s still there—how do you tell git to to “undo” tracking changes in this file? **Undo with:** `git rm --cached application.log` **What’s happening:** While `.gitignore` prevents Git from tracking changes to files or even noticing the existence of files it’s never tracked before, once a file has been added and committed, Git will continue noticing changes in that file. Similarly, if you’ve used `git add -f` to “force”, or override, `.gitignore`, Git will keep tracking changes. You won’t have to use `-f` to add it in the future. If you want to remove that should-be-ignored file from Git’s tracking, `git rm --cached` will remove it from tracking but leave the file untouched on disk. Since it’s now being ignored, you won’t see that file in `git status` or accidentally commit changes from that file again. *** That’s how to undo anything with Git. To learn more about any of the Git commands used here, check out the relevant documentation: - [checkout](http://git-scm.com/docs/git-checkout) - [commit](http://git-scm.com/docs/git-commit) - [rebase](http://git-scm.com/docs/git-rebase) - [reflog](http://git-scm.com/docs/git-reflog) - [reset](http://git-scm.com/docs/git-reset) - [revert](http://git-scm.com/docs/git-revert) - [rm](http://git-scm.com/docs/git-rm) ## Written by ![Joshua Wehner](https://avatars0.githubusercontent.com/u/2077?v=4&s=200)
Shard129 (laksa)
Root Hash7620767358965441529
Unparsed URLblog,github!/open-source/git/how-to-undo-almost-anything-with-git/ s443