Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'doc/topics/git/numerous_undo_possibilities_in_git/index.md')
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md366
1 files changed, 142 insertions, 224 deletions
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
index eba471882f1..b151ddfff71 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -5,289 +5,215 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Numerous undo possibilities in Git **(FREE)**
+# Undo possibilities in Git **(FREE)**
-This tutorial shows you different ways of undoing your work in Git.
-We assume you have a basic working knowledge of Git. Check the GitLab
-[Git documentation](../index.md) for reference.
+[Nothing in Git is deleted](https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery),
+so when you work in Git, you can undo your work.
-We only provide some general information about the commands to get you started.
-For more advanced examples, refer to the [Git book](https://git-scm.com/book/en/v2).
+All version control systems have options for undoing work. However,
+because of the de-centralized nature of Git, these options are multiplied.
+The actions you take are based on the
+[stage of development](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository)
+you are in.
-A few different techniques exist to undo your changes, based on the stage
-of the change in your current development. Remember that
-[nothing in Git is really deleted](https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery).
-Until Git cleans detached commits - commits that cannot be accessed by branch or tag -
-you can view them with `git reflog` command, and access them with direct commit ID.
-Read more about [redoing the undo](#redoing-the-undo) in the section below.
+For more information about working with Git and GitLab:
-> For more information about working with Git and GitLab:
->
-> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Learn why [North Western Mutual chose GitLab](https://youtu.be/kPNMyxKRRoM) for their Enterprise source code management.
-> - Learn how to [get started with Git](https://about.gitlab.com/resources/whitepaper-moving-to-git/).
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Learn why [North Western Mutual chose GitLab](https://youtu.be/kPNMyxKRRoM) for their enterprise source code management.
+- Learn how to [get started with Git](https://about.gitlab.com/resources/whitepaper-moving-to-git/).
+- For more advanced examples, refer to the [Git book](https://git-scm.com/book/en/v2).
-## Introduction
+## When you can undo changes
-This guide is organized depending on the [stage of development](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository):
+In the standard Git workflow:
-- Where do you want to undo your changes from?
-- Were they shared with other developers?
+1. You create or edit a file. It starts in the unstaged state. If it's new, it is not yet tracked by Git.
+1. You add the file to your local repository (`git add`), which puts the file into the staged state.
+1. You commit the file to your local repository (`git commit`).
+1. You can then share the file with other developers, by committing to a remote repository (`git push`).
-Because Git tracks changes, a created or edited file is in the unstaged state
-(if created it is untracked by Git). After you add it to a repository (`git add`) you put
-a file into the **staged** state, which is then committed (`git commit`) to your
-local repository. After that, file can be shared with other developers (`git push`).
-This tutorial covers:
+You can undo changes at any point in this workflow:
-- [Undo local changes](#undo-local-changes) which were not pushed to a remote repository:
-
- - Before you commit, in both unstaged and staged state.
- - After you committed.
-
-- Undo changes after they are pushed to a remote repository:
-
- - [Without history modification](#undo-remote-changes-without-changing-history) (preferred way).
- - [With history modification](#undo-remote-changes-with-modifying-history) (requires
+- [When you're working locally](#undo-local-changes) and haven't yet pushed to a remote repository.
+- When you have already pushed to a remote repository and you want to:
+ - [Keep the history intact](#undo-remote-changes-without-changing-history) (preferred).
+ - [Change the history](#undo-remote-changes-with-modifying-history) (requires
coordination with team and force pushes).
- - [Use cases when modifying history is generally acceptable](#where-modifying-history-is-generally-acceptable).
- - [How to modify history](#how-modifying-history-is-done).
- - [How to remove sensitive information from repository](#deleting-sensitive-information-from-commits).
-### Branching strategy
+## Undo local changes
-[Git](https://git-scm.com/) is a de-centralized version control system. Beside regular
-versioning of the whole repository, it has possibilities to exchange changes
-with other repositories.
+Until you push your changes to a remote repository, changes
+you make in Git are only in your local development environment.
-To avoid chaos with
-[multiple sources of truth](https://git-scm.com/about/distributed), various
-development workflows have to be followed. It depends on your internal
-workflow how certain changes or commits can be undone or changed.
+### Undo unstaged local changes
-[GitLab Flow](https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/) provides a good
-balance between developers clashing with each other while
-developing the same feature and cooperating seamlessly. However, it does not enable
-joined development of the same feature by multiple developers by default.
+When you make a change, but have not yet staged it, you can undo your work.
-When multiple developers develop the same feature on the same branch, clashing
-with every synchronization is unavoidable. However, a proper or chosen Git Workflow
-prevents lost or out-of-sync data when the feature is complete.
+1. Confirm that the file is unstaged (that you did not use `git add <file>`) by running `git status`:
-You can also
-read through this blog post on [Git Tips & Tricks](https://about.gitlab.com/blog/2016/12/08/git-tips-and-tricks/)
-to learn how to do things in Git.
+ ```shell
+ $ git status
+ On branch main
+ Your branch is up-to-date with 'origin/main'.
+ Changes not staged for commit:
+ (use "git add <file>..." to update what will be committed)
+ (use "git checkout -- <file>..." to discard changes in working directory)
-## Undo local changes
+ modified: <file>
+ no changes added to commit (use "git add" and/or "git commit -a")
+ ```
-Until you push your changes to any remote repository, they only affect you.
-That broadens your options on how to handle undoing them. Still, local changes
-can be on various stages and each stage has a different approach on how to tackle them.
+1. Choose an option and undo your changes:
-### Unstaged local changes (before you commit)
+ - To overwrite local changes:
-When a change is made, but not added to the staged tree, Git
-proposes a solution to discard changes to the file.
+ ```shell
+ git checkout -- <file>
+ ```
-Suppose you edited a file to change the content using your favorite editor:
+ - To save local changes so you can [re-use them later](#quickly-save-local-changes):
-```shell
-vim <file>
-```
+ ```shell
+ git stash
+ ```
-Because you did not `git add <file>` to staging, it should be under unstaged files (or
-untracked if file was created). You can confirm that with:
+ - To discard local changes to all files, permanently:
-```shell
-$ git status
-On branch master
-Your branch is up-to-date with 'origin/master'.
-Changes not staged for commit:
- (use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
- modified: <file>
-no changes added to commit (use "git add" and/or "git commit -a")
-```
+ ```shell
+ git reset --hard
+ ```
-At this point there are 3 options to undo the local changes you have:
+### Undo staged local changes
-- Discard all local changes, but save them for possible re-use [later](#quickly-save-local-changes):
+If you added a file to staging, you can undo it.
- ```shell
- git stash
- ```
+1. Confirm that the file is staged (that you used `git add <file>`) by running `git status`:
-- Discarding local changes (permanently) to a file:
+ ```shell
+ $ git status
+ On branch main
+ Your branch is up-to-date with 'origin/main'.
+ Changes to be committed:
+ (use "git restore --staged <file>..." to unstage)
- ```shell
- git checkout -- <file>
- ```
+ new file: <file>
+ ```
-- Discard all local changes to all files permanently:
+1. Choose an option and undo your changes:
- ```shell
- git reset --hard
- ```
+ - To unstage the file but keep your changes:
-Before executing `git reset --hard`, keep in mind that there is also a way to
-just temporary store the changes without committing them using `git stash`.
-This command resets the changes to all files, but it also saves them in case
-you would like to apply them at some later time. You can read more about it in
-[section below](#quickly-save-local-changes).
+ ```shell
+ git restore --staged <file>
+ ```
-### Quickly save local changes
+ - To unstage everything but keep your changes:
-You are working on a feature when a boss drops by with an urgent task. Because your
-feature is not complete, but you need to swap to another branch, you can use
-`git stash` to:
+ ```shell
+ git reset
+ ```
-- Save what you have done.
-- Swap to another branch.
-- Commit, push, and test.
-- Return to the feature branch.
-- Run `git stash pop`.
-- Resume your work.
+ - To unstage the file to current commit (HEAD):
-The example above shows that discarding all changes is not always a preferred option.
-However, Git provides a way to save them for later, while resetting the repository to state without
-them. This is achieved by Git stashing command `git stash`, which in fact saves your
-current work and runs `git reset --hard`, but it also has various
-additional options like:
+ ```shell
+ git reset HEAD <file>
+ ```
-- `git stash save`, which enables including temporary commit message, which helps you identify changes, among with other options
-- `git stash list`, which lists all previously stashed commits (yes, there can be more) that were not `pop`ed
-- `git stash pop`, which redoes previously stashed changes and removes them from stashed list
-- `git stash apply`, which redoes previously stashed changes, but keeps them on stashed list
+ - To discard all local changes, but save them for [later](#quickly-save-local-changes):
-### Staged local changes (before you commit)
+ ```shell
+ git stash
+ ```
-If you add some files to staging, but you want to remove them from the
-current commit while retaining those changes, move them outside
-of the staging tree. You can also discard all changes with
-`git reset --hard` or think about `git stash` [as described earlier.](#quickly-save-local-changes)
+ - To discard everything permanently:
-Lets start the example by editing a file with your favorite editor to change the
-content and add it to staging:
+ ```shell
+ git reset --hard
+ ```
-```shell
-vim <file>
-git add <file>
-```
-
-The file is now added to staging as confirmed by `git status` command:
-
-```shell
-$ git status
-On branch master
-Your branch is up-to-date with 'origin/master'.
-Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
- new file: <file>
-```
+### Quickly save local changes
-Now you have 4 options to undo your changes:
+If you want to change to another branch, you can use [`git stash`](https://www.git-scm.com/docs/git-stash).
-- Unstage the file to current commit (HEAD):
+1. From the branch where you want to save your work, type `git stash`.
+1. Swap to another branch (`git checkout <branchname>`).
+1. Commit, push, and test.
+1. Return to the branch where you want to resume your changes.
+1. Use `git stash list` to list all previously stashed commits.
+1. Run a version of `git stash`:
- ```shell
- git reset HEAD <file>
- ```
+ - Use `git stash pop` to redo previously stashed changes and remove them from stashed list.
+ - Use `git stash apply` to redo previously stashed changes, but keep them on stashed list.
-- Unstage everything - retain changes:
+## Undo committed local changes
- ```shell
- git reset
- ```
+When you commit to your local repository (`git commit`), the version control system records
+your changes. Because you did not push to a remote repository yet, your changes are
+not public (or shared with other developers). At this point, you can undo your changes.
-- Discard all local changes, but save them for [later](#quickly-save-local-changes):
+### Undo staged local changes without modifying history
- ```shell
- git stash
- ```
+You can revert a commit while retaining the commit history.
-- Discard everything permanently:
+This example uses five commits `A`,`B`,`C`,`D`,`E`, which were committed in order: `A-B-C-D-E`.
+The commit you want to undo is `B`.
- ```shell
- git reset --hard
- ```
+1. Find the commit SHA of the commit you want to revert to. To look
+ through a log of commits, type `git log`.
+1. Choose an option and undo your changes:
-## Committed local changes
+ - To swap additions and deletions changes introduced by commit `B`:
-After you commit, your changes are recorded by the version control system.
-Because you haven't pushed to your remote repository yet, your changes are
-still not public (or shared with other developers). At this point, undoing
-things is a lot easier, we have quite some workaround options. After you push
-your code, you have fewer options to troubleshoot your work.
+ ```shell
+ git revert <commit-B-SHA>
+ ```
-### Without modifying history
+ - To undo changes on a single file or directory from commit `B`, but retain them in the staged state:
-Through the development process some of the previously committed changes do not
-fit anymore in the end solution, or are source of the bugs. After you find the
-commit which triggered bug, or identify a faulty commit, you can
-revert it with `git revert commit-id`.
+ ```shell
+ git checkout <commit-B-SHA> <file>
+ ```
-This command inverts (swaps) the additions and
-deletions in that commit, so that it does not modify history. Retaining history
-can be helpful in future to notice that some changes have been tried
-unsuccessfully in the past.
+ - To undo changes on a single file or directory from commit `B`, but retain them in the unstaged state:
-In our example we assume there are commits `A`,`B`,`C`,`D`,`E` committed in this order: `A-B-C-D-E`,
-and `B` is the commit you want to undo. There are many different ways to identify commit
-`B` as bad. One of them is to pass a range to `git bisect` command. The provided range includes
-last known good commit (we assume `A`) and first known bad commit where the bug was detected (we assume `E`).
+ ```shell
+ git reset <commit-B-SHA> <file>
+ ```
-```shell
-git bisect A..E
-```
+#### Undo multiple committed changes
-Bisect provides us with commit ID of the middle commit to test, and then guide us
-through the bisection process. You can read more about it [in official Git Tools](https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git)
-Our example results in commit `B`, which introduced the bug/error. We have
-these options to remove all or part of it from our repository:
+You can recover from multiple commits. For example, if you have done commits `A-B-C-D`
+on your feature branch and then realize that `C` and `D` are wrong.
-- Undo (swap additions and deletions) changes introduced by commit `B`:
+To recover from multiple incorrect commits:
- ```shell
- git revert commit-B-id
- ```
+1. Check out the last correct commit. In this example, `B`.
-- Undo changes on a single file or directory from commit `B`, but retain them in the staged state:
+ ```shell
+ git checkout <commit-B-SHA>
+ ```
- ```shell
- git checkout commit-B-id <file>
- ```
+1. Create a new branch.
-- Undo changes on a single file or directory from commit `B`, but retain them in the unstaged state:
+ ```shell
+ git checkout -b new-path-of-feature
+ ```
- ```shell
- git reset commit-B-id <file>
- ```
+1. Add, push, and commit your changes.
-- There is one command we also must not forget: **creating a new branch**
- from the point where changes are not applicable or where the development has hit a
- dead end. For example you have done commits `A-B-C-D` on your feature branch
- and then you figure `C` and `D` are wrong.
+The commits are now `A-B-C-D-E`.
- At this point you either reset to `B`
- and do commit `F` (which causes problems with pushing and if forced pushed also with other developers)
- because the branch now looks `A-B-F`, which clashes with what other developers have locally (you will
- [change history](#with-history-modification)), or you checkout commit `B` create
- a new branch and do commit `F`. In the last case, everyone else can still do their work while you
- have your new way to get it right and merge it back in later. Alternatively, with GitLab,
- you can [cherry-pick](../../../user/project/merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
- that commit into a new merge request.
+Alternatively, with GitLab,
+you can [cherry-pick](../../../user/project/merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
+that commit into a new merge request.
- ![Create a new branch to avoid clashing](img/branching.png)
+NOTE:
+Another solution is to reset to `B` and commit `E`. However, this solution results in `A-B-E`,
+which clashes with what other developers have locally.
- ```shell
- git checkout commit-B-id
- git checkout -b new-path-of-feature
- # Create <commit F>
- git commit -a
- ```
+### Undo staged local changes with history modification
-### With history modification
+You can rewrite history in Git, but you should avoid it, because it can cause problems
+when multiple developers are contributing to the same codebase.
There is one command for history modification and that is `git rebase`. Command
provides interactive mode (`-i` flag) which enables you to:
@@ -335,7 +261,7 @@ In case you want to modify something introduced in commit `B`.
You can find some more examples in the section explaining
[how to modify history](#how-modifying-history-is-done).
-### Redoing the Undo
+### Redoing the undo
Sometimes you realize that the changes you undid were useful and you want them
back. Well because of first paragraph you are in luck. Command `git reflog`
@@ -379,7 +305,7 @@ it also provides a clear timeline and development structure.
![Use revert to keep branch flowing](img/revert.png)
-If you want to revert changes introduced in certain `commit-id`, you can
+If you want to revert changes introduced in certain `commit-id`, you can
revert that `commit-id` (swap additions and deletions) in newly created commit:
You can do this with
@@ -501,14 +427,6 @@ feature set as `git filter-branch` does, but focus on specific use cases.
Refer [Reduce repository size](../../../user/project/repository/reducing_the_repo_size_using_git.md) page to know more about purging files from repository history & GitLab storage.
-## Conclusion
-
-Various options exist for undoing your work with any version control system, but
-because of the de-centralized nature of Git, these options are multiplied (or limited)
-depending on the stage of your process. Git also enables rewriting history, but that
-should be avoided as it might cause problems when multiple developers are
-contributing to the same codebase.
-
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues