From a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 16 Jun 2021 18:25:58 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-0-stable-ee --- .../numerous_undo_possibilities_in_git/index.md | 218 +++++++++------------ 1 file changed, 93 insertions(+), 125 deletions(-) (limited to 'doc/topics/git/numerous_undo_possibilities_in_git/index.md') 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 b151ddfff71..6de62897041 100644 --- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md +++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md @@ -36,7 +36,7 @@ You can undo changes at any point in this workflow: - [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 + - [Change the history](#undo-remote-changes-while-changing-history) (requires coordination with team and force pushes). ## Undo local changes @@ -139,6 +139,12 @@ If you want to change to another branch, you can use [`git stash`](https://www.g 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. + + ```shell + stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation + stash@{1}: On master: 9cc0589... Add git-stash + ``` + 1. Run a version of `git stash`: - Use `git stash pop` to redo previously stashed changes and remove them from stashed list. @@ -146,7 +152,7 @@ If you want to change to another branch, you can use [`git stash`](https://www.g ## Undo committed local changes -When you commit to your local repository (`git commit`), the version control system records +When you commit to your local repository (`git commit`), Git 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. @@ -212,64 +218,53 @@ which clashes with what other developers have locally. ### Undo staged local changes 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: +The following tasks rewrite Git history. -- **reword** commit messages (there is also `git commit --amend` for editing - last commit message). -- **edit** the commit content (changes introduced by commit) and message. -- **squash** multiple commits into a single one, and have a custom or aggregated - commit message. -- **drop** commits - delete them. -- and few more options. +#### Delete a specific commit -Let us check few examples. Again there are commits `A-B-C-D` where you want to -delete commit `B`. +You can delete a specific commit. For example, if you have +commits `A-B-C-D` and you want to delete commit `B`. -- Rebase the range from current commit D to A: +1. Rebase the range from current commit `D` to `B`: - ```shell - git rebase -i A - ``` + ```shell + git rebase -i A + ``` -- Command opens your favorite editor where you write `drop` in front of commit - `B`, but you leave default `pick` with all other commits. Save and exit the - editor to perform a rebase. Remember: if you want to cancel delete whole - file content before saving and exiting the editor + A list of commits is displayed in your editor. -In case you want to modify something introduced in commit `B`. +1. In front of commit `B`, replace `pick` with `drop`. +1. Leave the default, `pick`, for all other commits. +1. Save and exit the editor. -- Rebase the range from current commit D to A: +#### Modify a specific commit - ```shell - git rebase -i A - ``` +You can modify a specific commit. For example, if you have +commits `A-B-C-D` and you want to modify something introduced in commit `B`. -- Command opens your favorite text editor where you write `edit` in front of commit - `B`, but leave default `pick` with all other commits. Save and exit the editor to - perform a rebase. +1. Rebase the range from current commit `D` to `B`: -- Now do your edits and commit changes: + ```shell + git rebase -i A + ``` - ```shell - git commit -a - ``` + A list of commits is displayed in your editor. + +1. In front of commit `B`, replace `pick` with `edit`. +1. Leave the default, `pick`, for all other commits. +1. Save and exit the editor. +1. Open the file in your editor, make your edits, and commit the changes: -You can find some more examples in the section explaining -[how to modify history](#how-modifying-history-is-done). + ```shell + git commit -a + ``` ### 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` -enables you to *recall* detached local commits by referencing or applying them -via commit ID. Although, do not expect to see really old commits in reflog, because -Git regularly [cleans the commits which are *unreachable* by branches or tags](https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery). +You can recall previous local commits. However, not all previous commits are available, because +Git regularly [cleans the commits that are unreachable by branches or tags](https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery). -To view repository history and to track older commits you can use below command: +To view repository history and track prior commits, run `git reflog show`. For example: ```shell $ git reflog show @@ -287,89 +282,64 @@ eb37e74 HEAD@{6}: rebase -i (pick): Commit C 6e43d59 HEAD@{16}: commit: Commit B ``` -Output of command shows repository history. In first column there is commit ID, -in following column, number next to `HEAD` indicates how many commits ago something -was made, after that indicator of action that was made (commit, rebase, merge, ...) -and then on end description of that action. +This output shows the repository history, including: -## Undo remote changes without changing history +- The commit SHA. +- How many `HEAD`-changing actions ago the commit was made (`HEAD@{12}` was 12 `HEAD`-changing actions ago). +- The action that was taken, for example: commit, rebase, merge. +- A description of the action that changed `HEAD`. -This topic is roughly same as modifying committed local changes without modifying -history. **It should be the preferred way of undoing changes on any remote repository -or public branch.** Keep in mind that branching is the best solution when you want -to retain the history of faulty development, yet start anew from certain point. +## Undo remote changes without changing history -Branching -enables you to include the existing changes in new development (by merging) and -it also provides a clear timeline and development structure. +To undo changes in the remote repository, you can create a new commit with the changes you +want to undo. You should follow this process, which preserves the history and +provides a clear timeline and development structure. However, you +only need this procedure if your work was merged into a branch that +other developers use as the base for their work. ![Use revert to keep branch flowing](img/revert.png) -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 +To revert changes introduced in a specific commit `B`: ```shell -git revert commit-id +git revert B ``` -or creating a new branch: - -```shell -git checkout commit-id -git checkout -b new-path-of-feature -``` +## Undo remote changes while changing history -## Undo remote changes with modifying history +You can undo remote changes and change history. -This is useful when you want to *hide* certain things - like secret keys, -passwords, and SSH keys. It is and should not be used to hide mistakes, as -it makes it harder to debug in case there are some other bugs. The main -reason for this is that you loose the real development progress. Keep in -mind that, even with modified history, commits are just detached and can still be -accessed through commit ID - at least until all repositories perform -the automated cleanup of detached commits. +Even with an updated history, old commits can still be +accessed by commit SHA. This is the case at least until all the automated cleanup +of detached commits is performed, or a cleanup is run manually. Even the cleanup might not remove old commits if there are still refs pointing to them. ![Modifying history causes problems on remote branch](img/rebase_reset.png) -### Where modifying history is generally acceptable +### When changing history is acceptable -Modified history breaks the development chain of other developers, as changed -history does not have matching commit IDs. For that reason it should not be -used on any public branch or on branch that might be used by other developers. -When contributing to big open source repositories (for example, [GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md#contribution-acceptance-criteria) -itself), it is acceptable to squash commits into a single one, to present a -nicer history of your contribution. +You should not change the history when you're working in a public branch +or a branch that might be used by other developers. -Keep in mind that this also removes the comments attached to certain commits -in merge requests, so if you need to retain traceability in GitLab, then -modifying history is not acceptable. +When you contribute to large open source repositories, like [GitLab](https://gitlab.com/gitlab-org/gitlab), +you can squash your commits into a single one. -A feature branch of a merge request is a public branch and might be used by -other developers, but project process and rules might allow or require -you to use `git rebase` (command that changes history) to reduce number of -displayed commits on target branch after reviews are done (for example -GitLab). There is a `git merge --squash` command which does exactly that -(squashes commits on feature-branch to a single commit on target branch -at merge). +To squash commits on a feature branch to a single commit on a target branch +at merge, use `git merge --squash`. NOTE: -Never modify the commit history of `master` or shared branch. +Never modify the commit history of your [default branch](../../../user/project/repository/branches/default.md) or shared branch. -### How modifying history is done +### How to change history -After you know what you want to modify (how far in history or how which range of -old commits), use `git rebase -i commit-id`. This command displays all the commits from -current version to chosen commit ID and allow modification, squashing, deletion -of that commits. +A feature branch of a merge request is a public branch and might be used by +other developers. However, the project rules might require +you to use `git rebase` to reduce the number of +displayed commits on target branch after reviews are done. -```shell -$ git rebase -i commit1-id..commit3-id -pick -pick -pick +You can modify history by using `git rebase -i`. Use this command to modify, squash, +and delete commits. -# Rebase commit1-id..commit3-id onto (3 command(s)) +```shell # # Commands: # p, pick = use commit @@ -382,50 +352,48 @@ pick # # These lines can be re-ordered; they are executed from top to bottom. # -# If you remove a line here THAT COMMIT WILL BE LOST. +# If you remove a line THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # -# Note that empty commits are commented out +# Empty commits are commented out ``` NOTE: -The comment from the output clearly states that, if -you decide to abort, don't just close your editor (as that -modifies history), but remove all uncommented lines and save. +If you decide to stop a rebase, do not close your editor. +Instead, remove all uncommented lines and save. -Use `git rebase` carefully on -shared and remote branches, but rest assured: nothing is broken until -you push back to the remote repository (so you can freely explore the -different outcomes locally). +Use `git rebase` carefully on shared and remote branches. +Experiment locally before you push to the remote repository. ```shell # Modify history from commit-id to HEAD (current commit) git rebase -i commit-id ``` -### Deleting sensitive information from commits +### Delete sensitive information from commits + +You can use Git to delete sensitive information from your past commits. However, +history is modified in the process. + +To rewrite history with +[certain filters](https://git-scm.com/docs/git-filter-branch#_options), +run `git filter-branch`. -Git also enables you to delete sensitive information from your past commits and -it does modify history in the progress. That is why we have included it in this -section and not as a standalone topic. To do so, you should run the -`git filter-branch`, which enables you to rewrite history with -[certain filters](https://git-scm.com/docs/git-filter-branch#_options). -This command uses rebase to modify history and if you want to remove certain -file from history altogether use: +To remove a file from the history altogether use: ```shell git filter-branch --tree-filter 'rm filename' HEAD ``` -Because `git filter-branch` command might be slow on big repositories, there are -tools that can use some of Git specifics to enable faster execution of common -tasks (which is exactly what removing sensitive information file is about). +The `git filter-branch` command might be slow on large repositories. +Tools are available to execute Git commands more quickly. An alternative is the open source community-maintained tool [BFG](https://rtyley.github.io/bfg-repo-cleaner/). -Keep in mind that these tools are faster because they do not provide the same +These tools are faster because they do not provide the same 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. +Refer to [Reduce repository size](../../../user/project/repository/reducing_the_repo_size_using_git.md) to +learn more about purging files from repository history and GitLab storage.