Как изменить наименование коммита

If a commit message contains unclear, incorrect, or sensitive information, you can amend it locally and push a new commit with a new message to GitHub. You can also change a commit message to add missing information.

If a commit message contains unclear, incorrect, or sensitive information, you can amend it locally and push a new commit with a new message to GitHub. You can also change a commit message to add missing information.

Rewriting the most recent commit message

You can change the most recent commit message using the git commit --amend command.

In Git, the text of the commit message is part of the commit. Changing the commit message will change the commit ID—i.e., the SHA1 checksum that names the commit. Effectively, you are creating a new commit that replaces the old one.

Commit has not been pushed online

If the commit only exists in your local repository and has not been pushed to GitHub.com, you can amend the commit message with the git commit --amend command.

  1. On the command line, navigate to the repository that contains the commit you want to amend.

  2. Type git commit --amend and press Enter.

  3. In your text editor, edit the commit message, and save the commit.

    • You can add a co-author by adding a trailer to the commit. For more information, see «Creating a commit with multiple authors.»

    • You can create commits on behalf of your organization by adding a trailer to the commit. For more information, see «Creating a commit on behalf of an organization»

The new commit and message will appear on GitHub.com the next time you push.

You can change the default text editor for Git by changing the core.editor setting. For more information, see «Basic Client Configuration» in the Git manual.

Amending older or multiple commit messages

If you have already pushed the commit to GitHub.com, you will have to force push a commit with an amended message.

We strongly discourage force pushing, since this changes the history of your repository. If you force push, people who have already cloned your repository will have to manually fix their local history. For more information, see «Recovering from upstream rebase» in the Git manual.

Changing the message of the most recently pushed commit

  1. Follow the steps above to amend the commit message.
  2. Use the push --force-with-lease command to force push over the old commit.
    $ git push --force-with-lease origin EXAMPLE-BRANCH

Changing the message of older or multiple commit messages

If you need to amend the message for multiple commits or an older commit, you can use interactive rebase, then force push to change the commit history.

  1. On the command line, navigate to the repository that contains the commit you want to amend.

  2. Use the git rebase -i HEAD~n command to display a list of the last n commits in your default text editor.

    # Displays a list of the last 3 commits on the current branch
    $ git rebase -i HEAD~3

    The list will look similar to the following:

    pick e499d89 Delete CNAME
    pick 0c39034 Better README
    pick f7fde4a Change the commit message but push the same commit.
    
    # Rebase 9fdb3bd..f7fde4a onto 9fdb3bd
    #
    # Commands:
    # p, pick = use commit
    # r, reword = use commit, but edit the commit message
    # e, edit = use commit, but stop for amending
    # s, squash = use commit, but meld into previous commit
    # f, fixup = like "squash", but discard this commit's log message
    # x, exec = run command (the rest of the line) using shell
    #
    # These lines can be re-ordered; they are executed from top to bottom.
    #
    # If you remove a line here THAT COMMIT WILL BE LOST.
    #
    # However, if you remove everything, the rebase will be aborted.
    #
    # Note that empty commits are commented out
  3. Replace pick with reword before each commit message you want to change.

    pick e499d89 Delete CNAME
    reword 0c39034 Better README
    reword f7fde4a Change the commit message but push the same commit.
  4. Save and close the commit list file.

  5. In each resulting commit file, type the new commit message, save the file, and close it.

  6. When you’re ready to push your changes to GitHub, use the push —force command to force push over the old commit.

    $ git push --force origin EXAMPLE-BRANCH

For more information on interactive rebase, see «Interactive mode» in the Git manual.

As before, amending the commit message will result in a new commit with a new ID. However, in this case, every commit that follows the amended commit will also get a new ID because each commit also contains the id of its parent.

If you have included sensitive information in a commit message, force pushing a commit with an amended commit may not remove the original commit from GitHub. The old commit will not be a part of a subsequent clone; however, it may still be cached on GitHub and accessible via the commit ID. You must contact GitHub Support with the old commit ID to have it purged from the remote repository.

Further reading

  • «Signing commits»

On this question there are a lot of answers, but none of them explains in super detail how to change older commit messages using Vim. I was stuck trying to do this myself, so here I’ll write down in detail how I did this especially for people who have no experience in Vim!

I wanted to change my five latest commits that I already pushed to the server. This is quite ‘dangerous’ because if someone else already pulled from this, you can mess things up by changing the commit messages. However, when you’re working on your own little branch and are sure no one pulled it you can change it like this:

Let’s say you want to change your five latest commits, and then you type this in the terminal:

git rebase -i HEAD~5

*Where 5 is the number of commit messages you want to change (so if you want to change the 10th to last commit, you type in 10).

This command will get you into Vim there you can ‘edit’ your commit history. You’ll see your last five commits at the top like this:

pick <commit hash> commit message

Instead of pick you need to write reword. You can do this in Vim by typing in i. That makes you go in to insert mode. (You see that you’re in insert mode by the word INSERT at the bottom.) For the commits you want to change, type in reword instead of pick.

Then you need to save and quit this screen. You do that by first going in to ‘command-mode’ by pressing the Escbutton (you can check that you’re in command-mode if the word INSERT at the bottom has disappeared). Then you can type in a command by typing :. The command to save and quit is wq. So if you type in :wq you’re on the right track.

Then Vim will go over every commit message you want to reword, and here you can actually change the commit messages. You’ll do this by going into insert mode, changing the commit message, going into the command-mode, and save and quit. Do this five times and you’re out of Vim!

Then, if you already pushed your wrong commits, you need to git push --force to overwrite them. Remember that git push --force is quite a dangerous thing to do, so make sure that no one pulled from the server since you pushed your wrong commits!

Now you have changed your commit messages!

(As you see, I’m not that experienced in Vim, so if I used the wrong ‘lingo’ to explain what’s happening, feel free to correct me!)

Рабочий процесс в системе контроля версий git сводится к тому, что разработчик создает от ветки develop новую ветку для реализации конкретной задачи. Принято, что в ветке каждому коммиту соответствует более-менее логически законченная единица работы или же изменения, которые в будущем может потребоваться отменить.

Однако порой в спешке под конец рабочего дня разработчик может закоммититься с подписью вроде такой «WIP» или «TMP». В статье рассмотрим, как в git переименовать коммит. При этом возможны два основных случая — коммит является последним или коммит не является последним.

Переименование последнего коммита

На следующий день разработчик приходит на работу, просматривает изменения в ветке и вспоминает, что нужно изменить комментарий к коммиту. Для этого достаточно использовать команду git commit --amend -m "Новое название коммита".

Изменение комментария к не последнему коммиту

Допустим разработчик забыл с утра откорректировать название коммита, и в течение дня сделал ещё несколько коммитов. Тогда встаёт вопрос, как обновить комментарий, например для четвёртого коммита вглубь истории.

Итак, чтобы в git исправить комментарий такого коммита потребуется выполнить rebase в интерактивном режиме.

1. Сначала нужно посмотреть, на сколько коммитов назад находится тот коммит, которые нужно отредактировать. Для этого можно использоваться либо git log --oneline, либо консольный GUI для Git, например, tig.

Видим, что изменить комментарий нужно к коммиту «tmp», находящийся позади на четыре коммита относительно HEAD.

2. Теперь запускаем rebase в интерактивной режиме:

git rebase -i HEAD~5

3. В появившемся редакторе следует в строках коммитов изменить команду pick на reword.

Затем сохраняем файл и выходим.

4. Автоматически начнется ребейз и откроется файл редактирования коммита. Здесь необходимо ввести новую подпись к коммиту.

5. Остаётся сохранить и выйти. Теперь название коммита изменено.

Важно. Оба описанных способа приводят к изменению коммитов, а значит коммиты на сервере и в локальной ветке будут теперь отличаться. Поэтому запушить ветку так просто не получится — нужно использовать флаг --force.

git push --force

Однако, если работа в ветке ведётся несколькими разработчиками одновременно, тогда такой подход неприемлем.

Метки: Метки: git

Many times, when working with Git, you may want to revise your local commit history.
One of the great things about Git is that it allows you to make decisions at the last possible moment.
You can decide what files go into which commits right before you commit with the staging area, you can decide that you didn’t mean to be working on something yet with git stash, and you can rewrite commits that already happened so they look like they happened in a different way.
This can involve changing the order of the commits, changing messages or modifying files in a commit, squashing together or splitting apart commits, or removing commits entirely — all before you share your work with others.

In this section, you’ll see how to accomplish these tasks so that you can make your commit history look the way you want before you share it with others.

Note

Don’t push your work until you’re happy with it

One of the cardinal rules of Git is that, since so much work is local within your clone, you have a great deal of freedom to rewrite your history locally.
However, once you push your work, it is a different story entirely, and you should consider pushed work as final unless you have good reason to change it.
In short, you should avoid pushing your work until you’re happy with it and ready to share it with the rest of the world.

Changing the Last Commit

Changing your most recent commit is probably the most common rewriting of history that you’ll do.
You’ll often want to do two basic things to your last commit: simply change the commit message, or change the actual content of the commit by adding, removing and modifying files.

If you simply want to modify your last commit message, that’s easy:

The command above loads the previous commit message into an editor session, where you can make changes to the message, save those changes and exit.
When you save and close the editor, the editor writes a new commit containing that updated commit message and makes it your new last commit.

If, on the other hand, you want to change the actual content of your last commit, the process works basically the same way — first make the changes you think you forgot, stage those changes, and the subsequent git commit --amend replaces that last commit with your new, improved commit.

You need to be careful with this technique because amending changes the SHA-1 of the commit.
It’s like a very small rebase — don’t amend your last commit if you’ve already pushed it.

Tip

An amended commit may (or may not) need an amended commit message

When you amend a commit, you have the opportunity to change both the commit message and the content of the commit.
If you amend the content of the commit substantially, you should almost certainly update the commit message to reflect that amended content.

On the other hand, if your amendments are suitably trivial (fixing a silly typo or adding a file you forgot to stage) such that the earlier commit message is just fine, you can simply make the changes, stage them, and avoid the unnecessary editor session entirely with:

$ git commit --amend --no-edit

Changing Multiple Commit Messages

To modify a commit that is farther back in your history, you must move to more complex tools.
Git doesn’t have a modify-history tool, but you can use the rebase tool to rebase a series of commits onto the HEAD that they were originally based on instead of moving them to another one.
With the interactive rebase tool, you can then stop after each commit you want to modify and change the message, add files, or do whatever you wish.
You can run rebase interactively by adding the -i option to git rebase.
You must indicate how far back you want to rewrite commits by telling the command which commit to rebase onto.

For example, if you want to change the last three commit messages, or any of the commit messages in that group, you supply as an argument to git rebase -i the parent of the last commit you want to edit, which is HEAD~2^ or HEAD~3.
It may be easier to remember the ~3 because you’re trying to edit the last three commits, but keep in mind that you’re actually designating four commits ago, the parent of the last commit you want to edit:

Remember again that this is a rebasing command — every commit in the range HEAD~3..HEAD with a changed message and all of its descendants will be rewritten.
Don’t include any commit you’ve already pushed to a central server — doing so will confuse other developers by providing an alternate version of the same change.

Running this command gives you a list of commits in your text editor that looks something like this:

pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file

# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

It’s important to note that these commits are listed in the opposite order than you normally see them using the log command.
If you run a log, you see something like this:

$ git log --pretty=format:"%h %s" HEAD~3..HEAD
a5f4a0d Add cat-file
310154e Update README formatting and add blame
f7f3f6d Change my name a bit

Notice the reverse order.
The interactive rebase gives you a script that it’s going to run.
It will start at the commit you specify on the command line (HEAD~3) and replay the changes introduced in each of these commits from top to bottom.
It lists the oldest at the top, rather than the newest, because that’s the first one it will replay.

You need to edit the script so that it stops at the commit you want to edit.
To do so, change the word “pick” to the word “edit” for each of the commits you want the script to stop after.
For example, to modify only the third commit message, you change the file to look like this:

edit f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file

When you save and exit the editor, Git rewinds you back to the last commit in that list and drops you on the command line with the following message:

$ git rebase -i HEAD~3
Stopped at f7f3f6d... Change my name a bit
You can amend the commit now, with

       git commit --amend

Once you're satisfied with your changes, run

       git rebase --continue

These instructions tell you exactly what to do.
Type:

Change the commit message, and exit the editor.
Then, run:

This command will apply the other two commits automatically, and then you’re done.
If you change pick to edit on more lines, you can repeat these steps for each commit you change to edit.
Each time, Git will stop, let you amend the commit, and continue when you’re finished.

Reordering Commits

You can also use interactive rebases to reorder or remove commits entirely.
If you want to remove the “Add cat-file” commit and change the order in which the other two commits are introduced, you can change the rebase script from this:

pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file

to this:

pick 310154e Update README formatting and add blame
pick f7f3f6d Change my name a bit

When you save and exit the editor, Git rewinds your branch to the parent of these commits, applies 310154e and then f7f3f6d, and then stops.
You effectively change the order of those commits and remove the “Add cat-file” commit completely.

Squashing Commits

It’s also possible to take a series of commits and squash them down into a single commit with the interactive rebasing tool.
The script puts helpful instructions in the rebase message:

#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

If, instead of “pick” or “edit”, you specify “squash”, Git applies both that change and the change directly before it and makes you merge the commit messages together.
So, if you want to make a single commit from these three commits, you make the script look like this:

pick f7f3f6d Change my name a bit
squash 310154e Update README formatting and add blame
squash a5f4a0d Add cat-file

When you save and exit the editor, Git applies all three changes and then puts you back into the editor to merge the three commit messages:

# This is a combination of 3 commits.
# The first commit's message is:
Change my name a bit

# This is the 2nd commit message:

Update README formatting and add blame

# This is the 3rd commit message:

Add cat-file

When you save that, you have a single commit that introduces the changes of all three previous commits.

Splitting a Commit

Splitting a commit undoes a commit and then partially stages and commits as many times as commits you want to end up with.
For example, suppose you want to split the middle commit of your three commits.
Instead of “Update README formatting and add blame”, you want to split it into two commits: “Update README formatting” for the first, and “Add blame” for the second.
You can do that in the rebase -i script by changing the instruction on the commit you want to split to “edit”:

pick f7f3f6d Change my name a bit
edit 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file

Then, when the script drops you to the command line, you reset that commit, take the changes that have been reset, and create multiple commits out of them.
When you save and exit the editor, Git rewinds to the parent of the first commit in your list, applies the first commit (f7f3f6d), applies the second (310154e), and drops you to the console.
There, you can do a mixed reset of that commit with git reset HEAD^, which effectively undoes that commit and leaves the modified files unstaged.
Now you can stage and commit files until you have several commits, and run git rebase --continue when you’re done:

$ git reset HEAD^
$ git add README
$ git commit -m 'Update README formatting'
$ git add lib/simplegit.rb
$ git commit -m 'Add blame'
$ git rebase --continue

Git applies the last commit (a5f4a0d) in the script, and your history looks like this:

$ git log -4 --pretty=format:"%h %s"
1c002dd Add cat-file
9b29157 Add blame
35cfb2b Update README formatting
f7f3f6d Change my name a bit

This changes the SHA-1s of the three most recent commits in your list, so make sure no changed commit shows up in that list that you’ve already pushed to a shared repository.
Notice that the last commit (f7f3f6d) in the list is unchanged.
Despite this commit being shown in the script, because it was marked as “pick” and was applied prior to any rebase changes, Git leaves the commit unmodified.

Deleting a commit

If you want to get rid of a commit, you can delete it using the rebase -i script.
In the list of commits, put the word “drop” before the commit you want to delete (or just delete that line from the rebase script):

pick 461cb2a This commit is OK
drop 5aecc10 This commit is broken

Because of the way Git builds commit objects, deleting or altering a commit will cause the rewriting of all the commits that follow it.
The further back in your repo’s history you go, the more commits will need to be recreated.
This can cause lots of merge conflicts if you have many commits later in the sequence that depend on the one you just deleted.

If you get partway through a rebase like this and decide it’s not a good idea, you can always stop.
Type git rebase --abort, and your repo will be returned to the state it was in before you started the rebase.

If you finish a rebase and decide it’s not what you want, you can use git reflog to recover an earlier version of your branch.
See Data Recovery for more information on the reflog command.

Note

Drew DeVault made a practical hands-on guide with exercises to learn how to use git rebase.
You can find it at: https://git-rebase.io/

The Nuclear Option: filter-branch

There is another history-rewriting option that you can use if you need to rewrite a larger number of commits in some scriptable way — for instance, changing your email address globally or removing a file from every commit.
The command is filter-branch, and it can rewrite huge swaths of your history, so you probably shouldn’t use it unless your project isn’t yet public and other people haven’t based work off the commits you’re about to rewrite.
However, it can be very useful.
You’ll learn a few of the common uses so you can get an idea of some of the things it’s capable of.

Caution

git filter-branch has many pitfalls, and is no longer the recommended way to rewrite history.
Instead, consider using git-filter-repo, which is a Python script that does a better job for most applications where you would normally turn to filter-branch.
Its documentation and source code can be found at https://github.com/newren/git-filter-repo.

Removing a File from Every Commit

This occurs fairly commonly.
Someone accidentally commits a huge binary file with a thoughtless git add ., and you want to remove it everywhere.
Perhaps you accidentally committed a file that contained a password, and you want to make your project open source.
filter-branch is the tool you probably want to use to scrub your entire history.
To remove a file named passwords.txt from your entire history, you can use the --tree-filter option to filter-branch:

$ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
Rewrite 6b9b3cf04e7c5686a9cb838c3f36a8cb6a0fc2bd (21/21)
Ref 'refs/heads/master' was rewritten

The --tree-filter option runs the specified command after each checkout of the project and then recommits the results.
In this case, you remove a file called passwords.txt from every snapshot, whether it exists or not.
If you want to remove all accidentally committed editor backup files, you can run something like git filter-branch --tree-filter 'rm -f *~' HEAD.

You’ll be able to watch Git rewriting trees and commits and then move the branch pointer at the end.
It’s generally a good idea to do this in a testing branch and then hard-reset your master branch after you’ve determined the outcome is what you really want.
To run filter-branch on all your branches, you can pass --all to the command.

Making a Subdirectory the New Root

Suppose you’ve done an import from another source control system and have subdirectories that make no sense (trunk, tags, and so on).
If you want to make the trunk subdirectory be the new project root for every commit, filter-branch can help you do that, too:

$ git filter-branch --subdirectory-filter trunk HEAD
Rewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (12/12)
Ref 'refs/heads/master' was rewritten

Now your new project root is what was in the trunk subdirectory each time.
Git will also automatically remove commits that did not affect the subdirectory.

Changing Email Addresses Globally

Another common case is that you forgot to run git config to set your name and email address before you started working, or perhaps you want to open-source a project at work and change all your work email addresses to your personal address.
In any case, you can change email addresses in multiple commits in a batch with filter-branch as well.
You need to be careful to change only the email addresses that are yours, so you use --commit-filter:

$ git filter-branch --commit-filter '
        if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
        then
                GIT_AUTHOR_NAME="Scott Chacon";
                GIT_AUTHOR_EMAIL="schacon@example.com";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' HEAD

This goes through and rewrites every commit to have your new address.
Because commits contain the SHA-1 values of their parents, this command changes every commit SHA-1 in your history, not just those that have the matching email address.

Intro

This tutorial will cover various methods of rewriting and altering Git history. Git uses a few different methods to record changes. We will discuss the strengths and weaknesses of the different methods and give examples of how to work with them. This tutorial discusses some of the most common reasons for overwriting committed snapshots and shows you how to avoid the pitfalls of doing so.

Git’s main job is to make sure you never lose a committed change. But it’s also designed to give you total control over your development workflow. This includes letting you define exactly what your project history looks like; however, it also creates the potential of losing commits. Git provides its history-rewriting commands under the disclaimer that using them may result in lost content.

Git has several mechanisms for storing history and saving changes. These mechanisms include: Commit --amend, git rebase and git reflog. These options give you powerful work flow customization options. By the end of this tutorial, you’ll be familiar with commands that will let you restructure your Git commits, and be able to avoid pitfalls that are commonly encountered when rewriting history.

Changing the Last Commit: git commit --amend

The git commit --amend command is a convenient way to modify the most recent commit. It lets you combine staged changes with the previous commit instead of creating an entirely new commit. It can also be used to simply edit the previous commit message without changing its snapshot. But, amending does not just alter the most recent commit, it replaces it entirely, meaning the amended commit will be a new entity with its own ref. To Git, it will look like a brand new commit, which is visualized with an asterisk (*) in the diagram below. There are a few common scenarios for using git commit --amend. We’ll cover usage examples in the following sections.

Git commit amend

Change most recent Git commit message

Let’s say you just committed and you made a mistake in your commit log message. Running this command when there is nothing staged lets you edit the previous commit’s message without altering its snapshot.

Premature commits happen all the time in the course of your everyday development. It’s easy to forget to stage a file or to format your commit message the wrong way. The --amend flag is a convenient way to fix these minor mistakes.

git commit --amend -m "an updated commit message"

Adding the -m option allows you to pass in a new message from the command line without being prompted to open an editor.

Changing committed files

The following example demonstrates a common scenario in Git-based development. Let’s say we’ve edited a few files that we would like to commit in a single snapshot, but then we forget to add one of the files the first time around. Fixing the error is simply a matter of staging the other file and committing with the --amend flag:

# Edit hello.py and main.py
git add hello.py
git commit 
# Realize you forgot to add the changes from main.py 
git add main.py 
git commit --amend --no-edit

The --no-edit flag will allow you to make the amendment to your commit without changing its commit message. The resulting commit will replace the incomplete one, and it will look like we committed the changes to hello.py and main.py in a single snapshot.

Don’t amend public commits

Amended commits are actually entirely new commits and the previous commit will no longer be on your current branch. This has the same consequences as resetting a public snapshot. Avoid amending a commit that other developers have based their work on. This is a confusing situation for developers to be in and it’s complicated to recover from.

Recap

To review, git commit --amend lets you take the most recent commit and add new staged changes to it. You can add or remove changes from the Git staging area to apply with a --amend commit. If there are no changes staged, a --amend will still prompt you to modify the last commit message log. Be cautious when using --amend on commits shared with other team members. Amending a commit that is shared with another user will potentially require confusing and lengthy merge conflict resolutions.

Changing older or multiple commits

To modify older or multiple commits, you can use git rebase to combine a sequence of commits into a new base commit. In standard mode, git rebase allows you to literally rewrite history — automatically applying commits in your current working branch to the passed branch head. Since your new commits will be replacing the old, it’s important to not use git rebase on commits that have been pushed public, or it will appear that your project history disappeared.

In these or similar instances where it’s important to preserve a clean project history, adding the -i option to git rebase allows you to run rebase interactive. This gives you the opportunity to alter individual commits in the process, rather than moving all commits. You can learn more about interactive rebasing and additional rebase commands on the git rebase page.

Changing committed files

During a rebase, the edit or e command will pause the rebase playback on that commit and allow you to make additional changes with git commit --amend Git will interrupt the playback and present a message:

Stopped at 5d025d1... formatting
You can amend the commit now, with

git commit --amend

Once you are satisfied with your changes, run

git rebase --continue

Multiple messages

Each regular Git commit will have a log message explaining what happened in the commit. These messages provide valuable insight into the project history. During a rebase, you can run a few commands on commits to modify commit messages.

  • Reword or ‘r’ will stop rebase playback and let you rewrite the individual commit message during.
  • Squash or ‘s’ during rebase playback, any commits marked s will be paused on and you will be prompted to edit the separate commit messages into a combined message. More on this in the squash commits section below.
  • Fixup or ‘f’ has the same combining effect as squash. Unlike squash, fixup commits will not interrupt rebase playback to open an editor to combine commit messages. The commits marked ‘f’ will have their messages discarded in-favor of the previous commit’s message.

Squash commits for a clean history

The s «squash» command is where we see the true utility of rebase. Squash allows you to specify which commits you want to merge into the previous commits. This is what enables a «clean history.» During rebase playback, Git will execute the specified rebase command for each commit. In the case of squash commits, Git will open your configured text editor and prompt to combine the specified commit messages. This entire process can be visualized as follows:

Git Tutorial: git rebase -i example

Note that the commits modified with a rebase command have a different ID than either of the original commits. Commits marked with pick will have a new ID if the previous commits have been rewritten.

Modern Git hosting solutions like Bitbucket now offer «auto squashing» features upon merge. These features will automatically rebase and squash a branch’s commits for you when utilizing the hosted solutions UI. For more info see «Squash commits when merging a Git branch with Bitbucket.»

Recap

Git rebase gives you the power to modify your history, and interactive rebasing allows you to do so without leaving a “messy” trail. This creates the freedom to make and correct errors and refine your work, while still maintaining a clean, linear project history.

The safety net: git reflog

Reference logs, or «reflogs» are a mechanism Git uses to record updates applied to tips of branches and other commit references. Reflog allows you to go back to commits even though they are not referenced by any branch or tag. After rewriting history, the reflog contains information about the old state of branches and allows you to go back to that state if necessary. Every time your branch tip is updated for any reason (by switching branches, pulling in new changes, rewriting history or simply by adding new commits), a new entry will be added to the reflog. In this section we will take a high level look at the git reflog command and explore some common uses.

Usage

This displays the reflog for the local repository.

git reflog --relative-date

This shows the reflog with relative date information (e.g. 2 weeks ago).

Example

To understand git reflog, let’s run through an example.

0a2e358 HEAD@{0}: reset: moving to HEAD~2
0254ea7 HEAD@{1}: checkout: moving from 2.2 to main
c10f740 HEAD@{2}: checkout: moving from main to 2.2

The reflog above shows a checkout from main to the 2.2 branch and back. From there, there’s a hard reset to an older commit. The latest activity is represented at the top labeled HEAD@{0}.

If it turns out that you accidentally moved back, the reflog will contain the commit main pointed to (0254ea7) before you accidentally dropped 2 commits.

git reset --hard 0254ea7

Using Git reset, it is now possible to change main back to the commit it was before. This provides a safety net in case the history was accidentally changed.

It’s important to note that the reflog only provides a safety net if changes have been committed to your local repository and that it only tracks movements of the repositories branch tip. Additionally reflog entries have an expiration date. The default expiration time for reflog entries is 90 days.

For additional information, see our git reflog page. 

Summary

In this article we discussed several methods of changing git history, and undoing git changes. We took a high level look at the git rebase process. Some Key takeaways are:

  • There are many ways to rewrite history with git.
  • Use git commit --amend to change your latest log message.
  • Use git commit --amend to make modifications to the most recent commit.
  • Use git rebase to combine commits and modify history of a branch.
  • git rebase -i gives much more fine grained control over history modifications than a standard git rebase.

Learn more about the commands we covered at their individual pages:

  • git rebase
  • git reflog

Понравилась статья? Поделить с друзьями:
  • Как изменить наименование карточки товара на wb
  • Как изменить наименование канала на ютубе
  • Как изменить наименование ип казахстан
  • Как изменить наименование жесткого диска
  • Как изменить наименование единоличного исполнительного органа