If you accidentally committed your code to the wrong branch, you don’t have to redo the work. IntelliJ IDEA offers a low-stress solution by allowing you to move your commit to a different branch using Git’s cherry-pick option.
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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
We can copy the token into the Token field in the popup and click Log In.
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.
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.
We can change the search criteria to look for specific Merge Requests. We can use predefined filters, or search for something more specific.
If the Merge Request has assignees and/or reviewers assigned, we can see them here.
We can see the details of a specific Merge Request by double-clicking on it.
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.
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.
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.
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.
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.
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.
IntelliJ IDEA also shows if there are any conflicts, so we know if this request is safe to merge or not.
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).
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).
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.
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.
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.
We can also add comments from inside IntelliJ IDEA. We can place high-level comments, like the comment we just placed from GitLab.
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.
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.
From the diff viewer, we can submit our review and approve the Merge Request if we think it’s ready to be merged.
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.
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.
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.
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.
The Merge Request will be merged, and if we do a Fetch we can see the updated branches for this repository.
We can see in our browser that the Merge Request has been closed.
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.
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)
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.
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.
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).
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.
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.
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.
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).
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.
If we don’t have access to the original project, we need to push our code to our fork.
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.
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.
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.
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.
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?
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.
Once we’re back on the main branch, we can create a new branch named “bugfix”.
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.
Cherry-pick from the command line
Yes, we can do this from the command linetoo, 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).
As we can see, the bugfix commit is now on the bugfix branch.
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).
We can also filter commits in the commit log 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.
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.
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.
The cherry picked changes are transferred to the change list and we can commit them from there.
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.
We can resolve the merge conflicts here. We want to keep some changes, and reject others.
If you’re not able to resolve the merge conflicts, you can also abort the 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.
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.
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.
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.
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.
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.
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.
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…“.
This will open the “Rebasing Commits” popup window with a list of the commits that were done on top of the selected commit.
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.
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.
Now, because we want to combine those commits into one commit with one commit message we select “Fixup“, and then select “Start Rebasing“.
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“.
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“.
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.
This will open a “Edit Commit Message” popup, where you can edit the commit message and click “Ok” (or “Cancel“) when you are done.
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.)
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).
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.
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.
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.
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.
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.