IntelliJ IDEA: Selectively Commit Changes to a File

Sometimes you’re making multiple changes to a file that you don’t want to commit together. For example, if you’re working on a new feature, but notice some other small things you want to fix. If these changes are in separate files, we can commit each file separately. But what if they’re in the same file?

In IntelliJ IDEA (as of version 2023.3), we can now select which chunks and specific lines we want to add to our commit.

We can see which files were changed by opening the Commit tool window (⌘0 on macOS, or Alt+0  on Windows/Linux). Here we can open the diff for a particular file to see which changes were made to that file, using ⌘D (macOS) / Ctrl+D (Windows/Linux).

IntelliJ IDEA showing a diff in a file. There are multiple checkboxes in the gutter of the changed file for different changes to the file.

In the diff, we have the option to include specific changes to our commit, by clicking the Include into commit checkbox in the gutter next to each chunk of modified, deleted or newly added code.

IntelliJ IDEA showing a diff in a file and checkboxes in the gutter of the changed file. A tooltip on a checkbox shows "Include into commit".

We can even select specific lines from a change to include in a commit. To commit only a specific line from a chunk, right-click the line you want to include and select Split Chunk and Include Current Line into Commit.

IntelliJ IDEA showing a diff in a file with a checkbox in the gutter of the changed file. The context menu shows the option "Split Chunk and Include Current Line into Commit" highlighted.

Alternatively, hover over the gutter and select the checkbox next to the line you want to include in the commit. Or, if we change our mind, we can also hover over the gutter and clear the checkbox next to the line we want to exclude.

IntelliJ IDEA showing a diff in a file. There are multiple checkboxes in the gutter of the changed file. A tooltip on one of the checkboxes shows "Include into commit".

Once we have selected all the changes we want to commit, we write a meaningful commit message, and select Commit. Any unselected changes will stay in the current change list, so that you can commit them separately later.

What if we don’t want to add these changes to the same pull request, not even in a separate commit? Maybe you want to do some more cleaning up in your code base, and create a separate pull request for those changes later. We can undo this commit and move these changes to a different change list. To do so, select Move to Another Changelist from the context menu of a modified chunk.

IntelliJ IDEA showing a diff in a file with a checkbox in the gutter of the changed file and a context menu with the option "Move Lines to Another Changelist" highlighted.

Next, we can name our new changelist. The changes will be assigned to this changelist and we can see it in the Commit tool window.

IntelliJ IDEA showing a diff in a file with a popup on top. The popup is titled Move Lines to Another Changelist and the new changelist is named "Fixes".

Links

Working with GitLab Merge Requests in IntelliJ IDEA

In this tutorial, we will take a look at working with GitLab Merge Requests inside IntelliJ IDEA.

When reviewing Merge Requests in a web interface, we don’t have the same support that our IDE gives us, like syntax highlighting and the context within which the code was written.

IntelliJ IDEA has support for reviewing and merging GitLab Merge Requests. These features are available if the IntelliJ IDEA project has a remote that points to GitLab.

Remote

We can open the GitLab Merge Requests using the GitLab logo on the left, or from the menu by going to Git > Gitlab > Show Gitlab Merge Request.

Open Merge Requests from logo
Open Show GitLab Merge Requests from menu

Logging in to GitLab from IntelliJ IDEA

If we aren’t already logged in to GitLab via IntelliJ IDEA, the GitLab Merge Requests tool window will prompt us to Log In.

Log In

We can log into GitLab with a token. When we click Generate, this will take us to the GitLab page where a token with the right scopes can be generated for us. Click the button Create personal access token to create the token. When the token is generated, click the button to copy the token.

Generate a token
Create Personal Access Token
Copy the token

We can copy the token into the Token field in the popup and click Log In.

Paste the token into the Token field

Alternatively, we can use an existing token, as long as it has the required scopes.

We can also log in to our GitLab account in the Settings. Open the Settings (⌘, on macOS | Ctrl+Alt+S on Windows/Linux) and go to Version Control > GitLab. Click Add Account (⌘N on macOS | Alt+Insert on Windows/Linux) to add an account if there is no account logged in, or click the + button at the top left to add an account. In the popup, add the Server if needed, paste the token from GitLab into the Token field in the popup and click Log In.

Add GitLab account in Settings
Paste the token into the Token field in Settings
Account added in Settings

GitLab Merge Request tool window

Once we’re logged in, the GitLab Merge Requests tool window will show all open Merge Requests for the GitLab repository.

GitLab Merge Requests tool window

We can change the search criteria to look for specific Merge Requests. We can use predefined filters, or search for something more specific.

Filter
Search

If the Merge Request has assignees and/or reviewers assigned, we can see them here.

Assignee
Reviewer

We can see the details of a specific Merge Request by double-clicking on it.

Merge Request details

We can go back to the list of search results by clicking the project name in the top left of the Merge Requests tool window. We can see that the Merge Request we just looked at still has a tab open here, in case we want to go back.

Click project name to go back to the list of Merge Requests

Usually, you’ll want to look for open Merge Requests, since these are the ones that need attention. Let’s double-click, or press Enter, on one of these Merge Requests.

Open Merge Requests

View GitLab Merge Requests inside IntelliJ IDEA

If the Merge Request does not have a reviewer assigned, we can assign one from the Merge Request tool window in IntelliJ IDEA. Click the three dots at the bottom left of the Merge Request details and select the action Request Review. From the list that pops up, select the reviewer(s) to assign this Merge Request to.

Request Review
Assign reviewer

We can see the files that have been changed in the Merge Request in the bottom left window, and the timeline in the main editor pane.

Changed files and timeline

We can also select a file to see the diff as well as the comments for that file. We can go back to the timeline by clicking View Timeline.

The timeline shows the same information as the GitLab Merge Request activity page. The timeline shows activity on the Merge Request, including comments and other status changes in the main editor pane. If there are inline comments on the code, we can see them here.

It also shows the result of any checks that were run. We can go to the details to see which checks failed, and even click them to go straight to the failing check on GitLab, so we can look at the details.

Checks failed

We can open the Merge Request in our browser in several ways. We can right-click the Merge Request number and select Open in Browser. Alternatively, we can open the Merge Request in our browser by right-clicking it, either when it’s already open, or in the list of Merge Requests and selecting Open Merge Request in Browser.

Open on GitLab
Open in browser

IntelliJ IDEA also shows if there are any conflicts, so we know if this request is safe to merge or not.

Conflicts

We can open any of the files that make up the Merge Request, and IntelliJ IDEA will show them in the diff viewer, so we can have a closer look at the changes that make up the Merge Request. Inline comments will be displayed in the diff view too. Alternatively, we can open the diff view by selecting the file and using the shortcut for Show Diff (⌘D on macOS | Ctrl+D on Windows/Linux).

Show diff

If the Merge Request contains changes to multiple files, we can navigate between those files. We can do so using the arrows at the top of the diff viewer, or using the shortcuts to Compare Next File (⌃⇧→ on macOS | Alt+→ on Windows/Linux) or Compare Previous File (⌃⇧← on macOS |Alt+← on Windows/Linux).

Navigate between files

If the Merge Request consists of multiple commits, we can see the individual commits in the Changes from dropdown list. We can look at the changes for an individual commit if we want.

Multiple commits

We can also see the number of comments for the Merge Request, and for each file.

We can Hide All Windows (⇧⌘F12 on macOS | Ctrl+Shift+F12 on Windows/Linux) to focus on the diff. We can Restore Windows using the same shortcut.

Alternatively, we can reopen the Merge Requests window by opening the Recent Files dialog (⌘ E on macOS | Ctrl+E on Windows/Linux), which also lets us open up any of the Tool Windows. Here we can search for “merge” to find the Merge Request tool window.

Recent files

Adding comments from GitLab and IntelliJ IDEA

Let’s look at comments on our Merge Request.

We can add comments to the GitLab conversation. Comments on this page are comments that apply to the Merge Request as a whole, and not a specific piece of code. We can see these comments inside IntelliJ IDEA too. We might need to refresh our Merge Request window, either using the shortcut to Refresh Reviews (⌘R on macOS | Ctrl+F5 on Windows/Linux) or by right-clicking the Merge Request window and selecting Refresh Merge Request.

Comment from GitLab
Refresh reviews

We can also add comments from inside IntelliJ IDEA. We can place high-level comments, like the comment we just placed from GitLab.

Comment from IntelliJ IDEA

We might also want to add comments on particular parts of the code. We can do so from inside IntelliJ IDEA by clicking on the plus in the gutter of the diff viewer. For example, let’s add a comment to the current Merge Request.

Inline comment

We can edit or delete comments. We can also reply to comments or resolve a comment that is no longer relevant, for example, if the code has been updated in line with the comment.

Working with comments

From the diff viewer, we can submit our review and approve the Merge Request if we think it’s ready to be merged.

Submit Review and Approve

Reviewing GitLab Merge Requests inside IntelliJ IDEA

One feature that’s really helpful when we’re reviewing a Merge Request is that we can check out the code that is in the Merge Request. In this project, I’m currently on the main branch. Let’s check out the branch for this Merge Request.

Check out branch locally

With the branch checked out locally, we can navigate the code related to this Merge Request. This lets us not only look at the code, but also make sure that the project still builds and tests pass. We can potentially make changes too.

Build success

Finally, let’s look at how to finish off the Merge Request.

If a Merge Request is no longer relevant, and we’re not going to take the changes that went into the Merge Request, we can close it. We can do so by clicking the three dots at the bottom left of the Merge Request tool window and selecting Close Merge Request.

Close

If the Merge Request is ready, meaning all the checks have passed, questions have been answered and requested changes to the code have been made, we can merge it. We can do so by clicking the Merge button at the bottom left of the Merge Request window. We also have the option to Squash and Merge, meaning all commits will be combined into a single commit when merging. We can add our own commit message for the merge, or edit the default one if we want to.

Merge
Edit commit message

The Merge Request will be merged, and if we do a Fetch we can see the updated branches for this repository.

Fetch
Updated branches

We can see in our browser that the Merge Request has been closed.

Merged

Summary and shortcuts

As we’ve seen, we can work with GitLab Merge Requests right inside IntelliJ IDEA. We can see all Merge Requests on a project, filter them or search for a specific Merge Request, perform a code review and add comments, see whether checks have passed and there are no merge conflicts, checkout the branch to run it locally, submit our review and approve the Merge Request, and merge (or close) the Merge Request all from inside our IDE.

IntelliJ IDEA Shortcuts Used

Here are the IntelliJ IDEA shortcuts that we used.

NamemacOS ShortcutWindows / Linux Shortcut
Open Settings⌘,Ctrl+Alt+S
Add Account⌘NAlt+Insert
Show Diff⌘DCtrl+D
Compare Next File⌃⇧→Alt+→
Compare Previous File⌃⇧←Alt+←
Hide all windows / Restore windows⇧⌘F12Ctrl+Shift+F12
Recent files⌘ECtrl+E
Refresh reviews⌘RCtrl+F5
IntelliJ IDEA shortcuts used

Related Links

IntelliJ IDEA: GitLab Merge Requests

Overview of IntelliJ IDEA 2023

IntelliJ IDEA is designed to help developers like us stay in the flow while we’re working. Like all IDEs, it has a lot of functionality available, but it’s designed to get out of your way to let you focus on the code.

Take a look at this overview of IntelliJ IDEA.

Introduction

  • Find Action: ⌘ ⇧ A (on macOS) / Ctrl+Shift+A (on Windows/Linux)
  • Feature Trainer
  • Hide all windows: ⌘ ⇧ F12 (on macOS) / Shift+Command+F12 (on Windows/Linux)
  • Project tool window: ⌘1 (on macOS) / Alt+1 (on Windows/Linux)
  • Quick Switch Scheme: ^`(on macOS) / Ctrl+` (on Windows/Linux)
  • IDE viewing modes
  • Preferences: ⌘, (on macOS) / Ctrl+Alt+S (on Windows/Linux)

Coding assistance

  • Code completion
  • Complete Current Statement: ⌘ ⇧ ⏎ (on macOS) / Shift+Ctrl+Enter (on Windows/Linux)
  • Show Context Actions: ⌥ ⏎ (on macOS) / Alt+Enter (on Windows/Linux)
  • Intention actions
  • Navigate to next highlighted error: F2
  • Navigate to previous highlighted error: Shift F2
  • Generate code: ⌘ N (on macOS) / Alt + Insert (on Windows/Linux)
  • Live templates

Refactoring

  • Rename: Shift F6
  • Extend selection: ⌥ Up (on macOS) / Ctrl+W (on Windows/Linux)
  • Extract variable: ⌘ ⌥ V on macOS) / Ctrl+Alt+V (on Windows/Linux)
  • Postfix completion
  • Reformat code: ⌘ ⌥ L (on macOS) / Ctrl+Alt+L (on Windows/Linux)
  • Move statement up: ⇧⌘ Up (on macOS) / Ctrl+Shift+Up (on Windows/Linux)
  • Surround with: ⌘ ⌥ T (on macOS) / Ctrl+Alt+T (on Windows/Linux)
  • SmartType Completion: ^ ⇧ Space  (on macOS) / Shift+Ctrl+Space (on Windows/Linux)
  • Inline: ⌘ ⌥ N (on macOS) / Ctrl+Alt+N (on Windows/Linux)
  • Extract method: ⌘ ⌥ M on macOS) / Ctrl+Alt+M (on Windows/Linux)

Testing & Debugging

Navigation

  • Navigate backwards: ⌘ [ (on macOS) / Ctrl+Alt+Left (on Windows/Linux)
  • Navigate forwards: ⌘ ] (on macOS) / Ctrl+Alt+Right (on Windows/Linux)
  • Find usages / declaration: ⌘ B (on macOS) / Ctrl+B (on Windows/Linux)
  • Recent Files: ⌘E (on macOS) / Ctrl+E (on Windows/Linux)
  • Recent locations: ⇧⌘E (on macOS) / Ctrl+Shift+E (on Windows/Linux)
  • Search everywhere: ⇧⇧ (on macOS) / Shift Shift (on Windows/Linux)
  • Find in files: ⇧⌘F (on macOS) / Ctrl+Shift+F (on Windows/Linux)

Reading Code

  • Folding -> Expand: ⌘ + (on macOS) / Ctrl+ + (on Windows/Linux)
  • Folding -> Collapse: ⌘ – (on macOS) / Ctrl+ – (on Windows/Linux)
  • Folding -> Expand All : ⇧ ⌘ + (on macOS) / Ctrl+Shift+ + (on Windows/Linux)
  • Folding -> Collapse All: ⇧ ⌘ + (on macOS) / Ctrl+Shift+ – (on Windows/Linux)
  • File Structure: ⌘ F12 (macOS) / Ctrl+F12 (Windows/Linux) – Twice to expand list
  • Quick documentation: F1 (macOS) / Ctrl+Q (Windows/Linux)
  • Toggle Rendered View:  ^ ⌥ Q (macOS) / Ctrl+Alt+Q (Windows/Linux)

Version Control support (Git)

  • Commit: ⌘ 0 (macOS) / Alt+0 (Windows/Linux)
  • Jump to last tool window: F12
  • Show diff: ⌘ D (macOS) / Ctrl+D (Windows/Linux)
  • Commit Anyway and Push: ⌥ ⌘ K (on macOS) / Ctrl+Alt+K (on Windows/Linux)
  • Git tool window: ⌘9 (on macOS) / Alt+9 (on Windows/Linux)
  • Terminal: ⌥ F12 (on macOS) / Alt+F12 (on Windows/Linux)
  • Git integration

Language and technology support

Integrated tools support

Contributing to open source software; creating a pull request

In this tutorial, we are going to take a look at contributing to Open Source Software, specifically how to do a pull request (PR). We will look at forking and cloning the project, making the changes, committing and pushing these changes, creating the pull request, the review and hopefully merge of your PR. The same process may apply when making contributions to a project at work that you don’t own. In this example, the project is on GitHub. Other Git code repositories may use a similar process.

There are many reasons to contribute to open source projects, and different ways to find an issue to work on, from fixing a bug that is bothering you, to simply wanting to help out, or even just to gain more experience and learn something new. If you’re fixing something that is currently bothering you, you will have a specific issue and project to work on. If not, you could consider contributing to a project you like to use, or finding an issue that is suitable for someone new to contributing to open source and/or the project. There are also many different things you can contribute. Code is one, but projects also need testing and other things. For more information on what you can contribute and how to find something to contribute, please have a look at this video.

For this blog post, let’s assume we’ve found a project we want to work on, and an issue we want to fix.

Getting the project

When making your first contribution, you won’t have access to push to the open source project directly. So, the first thing we will need to do is fork this project to our own profile. This means we create a copy of the original project on our profile.

Fork project

Fork

We then need to clone this project to our local machine. We see that we have several options to get the code. Let’s use HTTPS as that can be the simplest option. When we click the clipboard icon, the URL will be copied to our clipboard.

Clone

Copied

When we open IntelliJ IDEA and don’t already have a project open, we’ll see the Welcome screen. Here we have the option to Get from VCS (version control system).

Welcome screen

When we click the button, the Get from Version Control dialog opens. We can paste the URL we just copied. We can select where we want to store this project on our computer; let’s stick with the default. When we select Clone, IntelliJ IDEA will clone the GitHub repository to the selected directory.

Clone project

If we already have a project open, we can open the Get from Version Control dialog by going to File > New > Project from version control.

New Project from version control menu

IntelliJ IDEA will open the project on our machine.

Making and committing our changes

Before making any changes, we’ll want to make sure that we can build the project. Hopefully, how to build the project will be described in the README, as it is for this example. Let’s open the terminal and build the project as described. In this example, we need Docker, which is already installed and running.

Build the project

Now that we know we can build the project, we can start making changes. First, we need to look for the right place to make the change. We might navigate the project in the Project tool window (⌘1 on macOS, or Alt+1 on Windows/Linux), or look for a specific file or code snippet using Find in Files (⌘⇧F on macOS, or Ctrl+Shift+F on Windows/Linux).

Project tool window

Find in files

We might want to create a specific branch for our changes.

Once we are done making our changes and the project still builds, we can commit our changes (⌘K on macOS, or Ctrl+K on Windows/Linux). We can check our changes in the Commit tool window (⌘1 on macOS, or Alt+1 on Windows/Linux) to see if these are the right files and use Show Diff (⌘D on macOS, or Ctrl+D on Windows/Linux) to see if the changes are correct.

Commit changes

Check the differences

If we don’t have access to the original project, we need to push our code to our fork.

Push

Creating the pull request

Once we are happy with our changes, we can create a pull request.

We go back to our GitHub profile and create a pull request from there. After we have pushed our changes, we can see that our fork is 1 commit ahead. We can start creating our pull request by clicking Contribute.

Contribute

We need to provide a title and description for our pull request. Make sure the title is a good description of the changes you want to contribute. If your PR fixes an issue, you can add “fixed #x” (where x is the issue number) to the title; this will automatically close the linked issue when the PR is merged. Once you are happy with the title and description, click the button Create pull request to open your pull request.

Open the pull request

Create pull request

Negotiating the review process

Now the waiting starts. On an active project, hopefully your PR will be reviewed soon. Your PR might get comments from reviewers that you need to fix. For complex changes, this might take several iterations. For smaller changes, hopefully it won’t. Before doing a lot of work on an issue you might want to check that your contribution is wanted and your solution is what they are looking for. Don’t be discouraged by review comments. Keep in mind that the maintainers will have to maintain your solution in the future and they want to make sure that it fits their project.

As you can see, reviewers can comment on your PR, approve the PR or request changes which must be addressed before merging. A project might have other checks set up that need to pass before merging. You might want to check that these checks pass and that there are no conflicts with the main branch.

Review

Checks

Summary and shortcuts

In this blog post, we’ve seen how to do an open source pull request. For more information on what you can contribute and how to find something to contribute, please have a look at this video.

IntelliJ IDEA Shortcuts Used

Here are the IntelliJ IDEA shortcuts that we used.

Name macOS Shortcut Windows / Linux Shortcut
Open / Close Project Tool Window ⌘1 Alt+1
Find in Files ⌘⇧F Ctrl+Shift+F
Commit changes ⌘K Ctrl+K
Commit tool window ⌘1 Alt+1
Show diff ⌘D Ctrl+D

Related Links

Cherry-pick: Move a commit to a different branch

There are several reasons why you might want to move a commit to a different branch. Let’s take a look at some of them.

Committed to the wrong branch

You’re working on a new feature, but an urgent bug came in. You fixed the bug and committed the fix, but oops… you forgot to create a new branch for the bugfix! Now this bugfix is on the wrong branch. How do we fix this?

IntelliJ IDEA Git log window showing a bugfix commit on a new-feature branch
Bugfix commit is on the wrong branch

Use cherry-pick to move the commit

I could redo the work, especially if it’s a small change, but … I don’t want to! Luckily, there is a better way.

We only want to move this one commit from the feature branch to a separate bugfix branch. We can do this using Git’s “cherry pick” option from IntelliJ IDEA.

First, let’s go back to main and create the bugfix branch that we should have created in the first place.

IntelliJ IDEA Git log window showing that the main branch is checked out.
Back on the main branch

Once we’re back on the main branch, we can create a new branch named “bugfix”.

Create a new Bugfix branch

On the newly created branch, we can select the bugfix commit from the other branch and select Cherry-Pick to apply that commit to our current branch.

IntelliJ IDEA Git log with the bugfix commit selected and the context menu with option cherry-pick selected.
Cherry Pick the selected commit from the context menu

Cherry-pick from the command line

Yes, we can do this from the command line too, but there’s no cute cherry icon on the command line. To cherry-pick a commit from the command line, we can use the command git cherry-pick <commit hash>. We would need to find the commit hash of the commit we want to cherry-pick, which we can find for example in the Commit Details pane in the Git log window (see below).

IntelliJ IDEA with the terminal open and the command "git cherry-pick 51e33e5a".
Cherry-pick on the command line

As we can see, the bugfix commit is now on the bugfix branch.

IntelliJ IDEA Git log showing the Bugfix commit on the bugfix branch and a message "Cherry-pick successful".
Cherry-pick successful

Other use cases for cherry-picking

Cherry picking can be useful in other situations too. Let’s take a look at some other use cases for cherry-picking.

Backporting a fix

We can also use cherry-picking to backport a fix to a previous release branch. For example, let’s move our bugfix commit also to the v1-release.

To do so, first we need to look for the last release (v1). We can search for a specific commit hash, branch or tag name in the Git log (⌘ F on Mac or Ctrl+F on Windows/Linux).

IntelliJ IDEA Git log showing a pop-up to Enter hash or branch/tag name.
Search Git log for Hash/Branch/Tag

We can also filter commits in the commit log by branch, user, date or path. 

IntelliJ IDEA Git log showing the option to filter by branch, user, date or path
Filter by branch, user, date or path

To see which commits have not yet been applied to this branch, we can click View Options and select Highlight | Not Cherry-Picked Commits. We’ll compare with the new-feature branch. Commits that have already been applied to the current branch are greyed out.

IntelliJ IDEA Git log showing a context menu with Highlights | Not Cherry-Picked Commits selected
Select the Not Cherry-Picked Commits

When we select a commit, we can look at the information in the Commit Details area (at the bottom right) to make sure these are the changes we want to transfer to this branch. In the Commit Details area we can see which files were changed in a particular commit. We can right-click a file and select Show Diff from the context menu to open the changes that were made to that file.

IntelliJ IDEA Git log showing the details of a commit on the right.
Look at the details of a commit

If we are sure these are the changes we want, we can cherry-pick them to the previous release branch.

Cherry pick part of a commit

In the Commit details pane on the right, select the files containing the changes you want to apply to the target branch, right-click and select Cherry-Pick Selected Changes from the context menu.

IntelliJ IDEA Git log showing a context-menu with the option Cherry-Pick Selected Changes selected
Cherry-Pick Selected Changes

The cherry picked changes are transferred to the change list and we can commit them from there. 

IntelliJ IDEA Commit window with Changes selected to be committed.
Partial commit added to the Change List to be committed

Dealing with conflicts

So far, cherry picking went smoothly because there are no conflicting changes. What if there are conflicts?!

When we cherry-pick a commit that has conflicts with our current branch, the Merge Conflicts dialog opens.

IntelliJ IDEA Merge Conflict dialog with the options to Accept Yours, Accept Theirs or Merge
Merge Conflict

We can resolve the merge conflicts here. We want to keep some changes, and reject others.

IntelliJ IDEA Merge Conflict dialog with conflicts highlighted
Merge Conflicts dialog
IntelliJ IDEA Merge Conflict dialog with conflicts resolved and the option to Save changes and finish merging
Merge conflicts have been resolved

If you’re not able to resolve the merge conflicts, you can also abort the cherry pick.

IntelliJ IDEA Git log showing a notification that the Cherry-pick was performed with conflicts and a popup to Abort the Cherry-Pick
Abort Cherry-pick

Continue after cherry-picking

Once we’re done cherry-picking, we can go back to the “feature” branch. Since we haven’t pushed these changes yet, we can remove the commit from the feature branch by selecting Drop commit

IntelliJ IDEA Git log with a commit selected and a context-menu with the option to Drop Commit
Drop Commit

What if you have pushed the changes already? Then you might want to revert it on this branch instead. Right-click the commit and from the context menu select Revert Commit.

IntelliJ IDEA Git log with a commit selected and a context-menu with the option to Revert Commit
Revert Commit

Now we can continue working on the new feature!

Conclusion

Moving a commit to a different branch. Not nearly as scary as it sounds! Let the IDE help to turn this into a quick, low-stress task.

Cherry pick a commit to a different branch in any JetBrains IDE

Links

Cherry pick a commit to a different branch

Oops, you committed your code to the wrong branch… You could redo the work, but you don’t want to! Luckily, the IDE can help you move your commit to a different branch. Use Git’s cherry-pick option from your IDE to move changes over to a different branch in a quick, low-stress way.

Cherry pick a commit to a different branch

Links

The Art of Cherry Picking

Oops, you committed your code to the wrong branch… You could redo the work, but you don’t want to! Luckily, the IDE can help you move your commit to a different branch. Use Git’s cherry-pick option from your IDE to move changes over to a different branch in a quick, low-stress way.

The Art of Cherry Picking

Links

IntelliJ IDEA: Resolving Merge Conflicts in Git

When you work in a team, you may come across a situation when somebody pushes changes to a file you are currently working on. If these changes do not overlap, the conflicting files are merged automatically. However, if the same lines were affected, Git cannot randomly pick one side over the other, and asks you to resolve the conflict. In this screencast, we’re going to take a look at resolving merge conflicts.

IntelliJ IDEA: Resolving Merge Conflicts in Git

Links

Using Git Interactive Rebase

This article was published on Foojay.io on August 25, 2022.

This tutorial will cover how to clean up your Git commit history with Git interactive rebase, both via the IntelliJ IDEA UI and from the command line.

Git interactive rebase allows you to change individual commits, squash commits together, drop commits or change the order of the commits.

This allows you to clean up your Git commit history to make it linear and meaningful, which can make it easier to understand the history of the project in the future.

Open the Git window in IntelliJ IDEA using ⌘+9 on Mac (or Alt+9 on Windows & Linux). In the Git log window we can see the commits that were made to the project.

We will use a Git demo project available on GitHub. This example uses TDD (Test Driven Development) to add a new feature.

In TDD, we start by adding a failing test, writing the minimum of code we need to get that test to pass and finally do some refactoring.

Even though we made the necessary changes in multiple commits, we don’t need to keep all these individual commits for future reference.

Using Git interactive rebase in the UI

We can use Git Interactive Rebase in IntelliJ IDEA as follows:

In the Git history, identify the commit from where you want to clean up your history. That will be the oldest commit in the series of commits you want to clean up; in this example, the first failing test that we added.

Right-click on the commit from where you want to clean up your history and select “Interactively Rebase from Here…“.

IntelliJ IDEA context menu with the option "Interactively Rebase from Here..." highlighted in blue

This will open the “Rebasing Commits” popup window with a list of the commits that were done on top of the selected commit.

IntelliJ IDEA "Rebase Commits" dialog

Notice there are several options at the top of this popup, that become active when we select one or more of the commits:

  • Reword allows us to change the commit message of a specific commit.
  • The Squash button is actually a dropdown that allows us to choose between Squash and Fixup. Both options will combine the changes made in the selected commits into one commit. If we select squash, by default the individual commit messages will be combined. If we select fixup, the commit message of the fixup commit will be discarded. You can select fixup while in the “Rebasing Commits” popup with ⌥+F on Mac (or Alt+F on Windows & Linux)
  • Drop allows us to drop one or more commits.

Changing the order of the commits

Let’s say we want to change the order of the commits; we want to keep the unrelated change, but separately from the changes for the new feature. We can select this commit and use the up and down buttons on the top left to change where in the order this commit will be.

List of commits in the "Rebase Commits" dialog window, with one commit selected.
List of commits in the "Rebase Commits" dialog window, with the  selected commit moved down.

Once we’re sure about the order, select “Start Rebasing“. We see in the Git log that the order of the commits has changed.

Combining multiple commits into one commit

Next, we want to combine multiple commits where we added the tests and implemented the new feature. Let’s reopen the “Rebasing Commits” window and select those commits.

List of commits in the "Rebase Commits" dialog window, with several commits in a row selected.

Now, because we want to combine those commits into one commit with one commit message we select “Fixup“, and then select “Start Rebasing“.

The Squash dropdown selected, with the Fixup option selected in the "Rebase Commits" dialog window.
List of selected commits in the "Rebase Commits" dialog window, shown in a tree structure ready for Fixup.

In the Git log, we can see that multiple individual commits are now combined into one commit with one commit message.

Drop a commit

Finally, we want to drop the commit with a mistake that we made. Let’s reopen the “Rebasing Commits” window, select the mistaken commit, select “Drop” and select “Start Rebasing“.

List of commits in the "Rebase Commits" dialog window, with one commits selected.
List of commits in the "Rebase Commits" dialog window, where the selected commit it shown with strike through.

We see in the Git log that the commit is dropped.

Rename a commit

Now that we have cleaned up our commit history, we might want to rename the commit where we added the new feature. We have several options to do so.

We can do so using Git interactive rebase, in the “Rebasing Commits” popup, by selecting the commit you want to rename and clicking the “Reword” button at the top of the popup. This will open a small editor pane where you can reword the commit message for this commit, apply the change to the message and select “Start Rebasing“.

Open dialog to Reword the commit message.

You can also edit the commit message directly in the Git log window. Right-click the commit you want to rename and select “Edit Commit Message” or press F2 on macOS, Windows or Linux.

IntelliJ IDEA context menu with option "Edit Commit Message" highlighted.

This will open a “Edit Commit Message” popup, where you can edit the commit message and click “Ok” (or “Cancel“) when you are done.

IntelliJ IDEA "Edit Commit Message" dialog.

See which Git commands were executed

To see which Git commands IntelliJ IDEA performed, open the “Console” tab in the Git window.

Using Git interactive rebase from the command line

Let’s take a look at how to use Git interactive rebase from the command line.

In the Git history, identify the commit just before the commit from where you want to clean up your history. In this example, that will be the last commit before we started adding the new feature.

Find the commit hash for this commit in the “Commit Details” to the right of the Git history in the Git window and copy this commit hash. (Spoiler: the commit hash in this example is 34bb0f99.)

IntelliJ IDEA Git history, showing the details of a selected commit, with the commit hash `34bb0f99` highlighted.

Open the Terminal window, using ⌥F12 on Mac (or Alt+F12 on Windows & Linux) and type git rebase -i 34bb0f99 (where 34bb0f99 is the commit hash we copied above).

Terminal with the command `git rebase -i 34bb0f99`

This will open an editor in the terminal with the list of commits that were done on top of the selected commit. Each line in this file is an individual commit.

Terminal with vi editor open, showing a list of commits.

By default, Git will use whatever you have set as your default text editor. If you haven’t set one, it will fall back to the vi editor, which is what we will use in this tutorial.

Changing the order of the commits

Let’s say we want to change the order of the commits; we want to keep the unrelated change, but separately from the changes for the new feature. We can do so by changing the order of the lines (individual commits) to reflect the order we want.

In the editor in the terminal, switch to edit mode by pressing I to be able to edit this file.

We can change the order of the lines by removing the commit we want to move from the list and inserting it in the place where we want it.

In vi, we can do so as follows:

  • Place the cursor anywhere on the line you want to move (in this example the commit “Unrelated changes”) and remove this line by typing dd.
  • Move the cursor to the line where you want to reinsert this commit (in this example, the end of the file) and type p.
  • Note: you do not need to switch to edit mode to do so.
Terminal with vi editor open, showing a list of commits. The bottom commit is highlighted.

Once we’re sure about the order, we need to save the file. Press esc to exit edit mode and type :wq to save the file.
Note: If you made changes to the file that you do not want to save, type :q! to force quit.

The interactive rebase will be applied. We see in the Git log that the order of the commits has changed.

Combining multiple commits into one commit

Next, we want to combine multiple commits where we added the tests and implemented the new feature. In the terminal, type git rebase -i 34bb0f99 to start rebasing. If you have already run this command, you can press the up arrow  in the terminal to show the last used command(s).

This will again open an editor in the terminal with the list of commits.

Switch to edit mode in the editor in the terminal. In vi, you can do so by pressing I.

For each of the commits we want to combine, replace “pick” with “fixup”.

Note that we use “fixup” because we want to use one commit message for the combination of the commits. Alternatively, we could use “squash” to combine the individual commit messages into the new commit message.

Terminal with vi editor open, showing a list of commits. For several commits `pick` is replaced with `fixup`.

Once we have correctly edited all the commits we want to combine, save the file.
In vi, press esc to exit edit mode and type :wq to save the file.
The interactive rebase will be applied. In the Git log, we can see that multiple individual commits are now combined into one commit with one commit message.

Drop a commit

Finally, we want to drop the commit with a mistake that we made. In the terminal, type git rebase -i 34bb0f99 to start rebasing.

To drop a commit, remove that commit from the list of commits. In this example, we will remove the commit “Mistake”.

In vi, we can remove a line by placing the cursor anywhere on the line we want to remove and typing dd. Alternatively, we can switch to edit mode by pressing I and removing the line manually. Press escto exit edit mode.

Terminal with vi editor open, showing a list of commits.

Save the file by typing :wq and the interactive rebase will be applied. We see in the Git log that the commit is dropped.

Summary

Now we know how to use git interactive rebase either from the IntelliJ IDEA UI or from the command line. Give them a try and use whichever way you prefer.

IntelliJ IDEA Shortcuts Used

Here are the IntelliJ IDEA shortcuts that we used.

NamemacOS ShortcutWindows / Linux Shortcut
Open the Git Tool Window⌘9Alt+9
Open the Commit Window⌘0Alt+0
Open the Terminal⌥F12Alt+F12
Select Fixup (in the “Rebasing Commits” popup)⌥F12Alt+F
Edit commit message (in the Git Log)F2F2
IntelliJ IDEA shortcuts

Git commands Used

Here are the Git commands that we used.

Nameterminal command
Git interactively rebase from a specific commit with commit hash, for example 11aa23bcgit rebase -i 11aa23bc
Use this commitpick
Fixup this commit (add changes to previous commit under the same commit message)fixup
Squash this commit (add changes to previous commit and combine commit messages)squash
Git commands

vi Shortcuts Used

Here are the shortcuts that we used.

NameShortcut
Open interactive (edit) modeI
Exit interactive (edit) modeesc
Remove line (note: not in edit mode)dd
Reinsert line (note: not in edit mode)p
Write and quit:wq
Force quit:q!
vi shortcuts

Related Links