Open-source News

Learn Git: 3 commands to level up your skill

opensource.com - Mon, 11/21/2022 - 16:00
Learn Git: 3 commands to level up your skill Dwayne McDaniel Mon, 11/21/2022 - 03:00

When I talk to people about Git, almost everyone has a strong reaction to the git rebase command. This command has caused many people to change directory, remove the repository, and just re-clone to start over. I think this comes from misconceptions about how branching actually works, a pretty terrible default interface, and some merge conflicts mucking things up.

Git squash

If you've ever made a lot of commits locally and wish there was a way to smash them all down into a single commit, you're in luck. Git calls this concept "squashing commits." I discovered the concept while working on documentation. It took me over a dozen commits to finally get a bit of markdown just right. The repo maintainer didn't want to see all my attempts cluttering up the project's history, so I was told to "just git squash your commits."

Squashing sounded like a solid plan. There was just one issue. I didn't know how to do it. As someone new to Git, I did what anyone would do. I consulted the manual for squash and immediately hit a snag:

$ man git-squash
> No manual entry for git-squash

It turns out I wasn't being told to run a Git command called squash, I was being asked to run an entirely separate command that would, in the end, combine all my commits into one. This is a common scenario: someone who has been using a tool for a while uses jargon or refers to a concept, which to them is absolutely clear, but isn't obvious to someone new to the tech.

Conceptually it would look like this:

Image by:

Photos by Dan Burton on Unsplash

I'm laying it out this way to encourage you that you are definitely not the first or last person that would be confused by Git or someone talking about Git. It's OK to ask for clarification and for help finding the right documentation. What that docs maintainer actually meant was, "use Git rebase to squash the commits into one."

More on Git What is Git? Git cheat sheet Markdown cheat sheet New Git articles Git rebase

The git rebase command removes a chain of commits away from its first parent and places it at the end of another chain of commits, combining both chains of commits into one long chain, instead of two parallel chains. I realize that's a dense statement.

If you think back to how Git commits are chained together, you can see that any branch aside from your initial main branch has a parent commit that serves as the "base" of that chain. Rebasing is the act of making the last commit in another chain the new "base" commit for a specified branch.

You might already be more familiar with Git merge. Take a look at how the git-scm.com site explains the difference:

Image by:

(Git-scm.com, CC BY-SA 3.0)

In this example merge, Git preserves the chain of commits shown in the image as C4, which has a parent of C2, when combining the changes in C3 to make a whole new commit, C5. The branch pointer for "experiment" still exists and still points at C4.

The rebase in this example shows a similar situation of C4 first existing as a separate branch with a parent of C2. But then, instead of merging with the code of C3, it makes C3 the new parent of C4, resulting in a new commit called C4. Notably, the branch pointer "main" has not moved yet. To make Git move the pointer to the end of the chain, currently pointed at by "experiment", you also need to perform a merge.

Rebase is not a replacement for merge. It's a tool for making cleaner histories to be used in conjunction with merge.

Interactive rebase is your best friend!

One of the scariest parts of performing a rebase from the command line is the horrifying interface. Running the command git rebase either works or blows up. There's not a lot of feedback or way to ensure it is doing what you precisely want. Fortunately, the rebase command and many other Git commands have an interactive mode, which you can invoke with the parameter -i' or –interactive`.

Image by:

(Dwayne McDaniel, CC BY-SA 4.0)

When invoking interactive mode, rebase transforms from a terrifying black box into a menu of options that let you do several things to the chain of commits you are rebasing. For every commit, you can choose to:

  • Pick: Include it as is

  • Reword: Rewrite the commit message

  • Edit: Make further changes to the files in the commit before the rebase finishes

  • Squash: Smash multiple commits into one commit, keeping all commit messages

  • Fixup: Smash multiple commits into one commit, but just keep the last commit message

  • Drop: Discard this commit

I personally like the way that the open source GitLens extension for VS Code lays out the options with dropdown picklists, but Git lets you assign these options using any editor. For text-only tools like Emacs or Vim, you need to type out the selection rather than pick from a menu, but the end result is still the same.

When to rebase

Knowing when to rebase is as important as knowing how to rebase. In truth, if you don't care about your repos histories being a bit messy, then you might never perform a rebase. But if you do want to make cleaner histories and have fewer commits cluttering up your graph view, then there is one clear rule of thumb to always keep in mind:

"Do not rebase commits that exist outside your repository and that people may have based work on."

If you follow that guideline, you'll be fine.

Simply put, if you make a local branch to do your work, feel free to rebase it all you want. But as soon as that branch is pushed, do not rebase it. It is really up to you.

Hopefully you found this helpful in understanding how the git rebase command works and can use it with more confidence. As with any Git command, practice is the only real way to learn and understand what is going on. I encourage you to brave and experiment with interactive rebase!

Git cherry-pick

Most developers have committed work only to realize they have been working on the wrong branch. Ideally, they could just pick up that one commit and move it over to the right branch. That is exactly what git cherry-pick does.

Cherry-picking is the art of rebasing single commits. This was so common of a pattern that they gave it its own command.

Image by:

(Crossroadsphotototeam, CC BY-SA 2.0)

To perform a cherry pick, you simply tell Git the ID of the commit you want to move to "here", where HEAD is pointing:

$ git cherry-pick <target-ref>

Should something go wrong, it's straightforward to recover, thanks to the error messages that Git provides:

$ git cherry-pick -i 2bc01cd
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not apply 2bc01cd… added EOF lines
hint: After resolving the conflicts, mark them with
hint: "git add/rm ", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
$ git cherry-pick --abortGit more power

The git rebase command is a powerful part of the Git utility. It's probably best to practice using it with a test repo before you have to use it under stress, but once you're familiar with its concepts and workflow, you can help provide a clear history of a repository's development.

Learn how to use git squash, git rebase, and git cherry-pick.

Image by:

Jonas Leupe on Unsplash

Git What to read next My favorite Git tools Git concepts in less than 10 minutes This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License. Register or Login to post a comment.

7 Git tips for technical writers

opensource.com - Mon, 11/21/2022 - 16:00
7 Git tips for technical writers Maximilian Kolb Mon, 11/21/2022 - 03:00

As a technical writer working for ATIX, my tasks include creating and maintaining documentation for Foreman at github.com/theforeman/foreman-documentation. Git helps me track versions of content, and to collaborate with the open source community. It's an integral part of storing the results of my work, sharing it, and discussing improvements. My main tools include my browser, OpenSSH to connect to Foreman instances, Vim to edit source files, and Git to version content.

This article focuses on recurring challenges when taking the first steps with Git and contributing to Foreman documentation. This is meant for intermediate Git users.

Prerequisites
  • You have installed and configured Git on your system. You must at least set your user name and email address.

  • You have an account on github.com. GitHub isn't an open source project itself, but it's the site where many open source Git repositories are stored (including Foreman's documentation.)

  • You have forked the foreman-documentation repository into your own account or organization (for example, github.com/My_Name/foreman-documentation. For more information, see A step-by-step guide to Git by Kedar Vijay Kulkarni.

  • You have added your SSH public key to GitHub. This is necessary to push your changes to GitHub. For more information, see A short introduction to GitHub by Nicole C. Baratta.

Contributing to Foreman documentation

Foreman is an open source project and thrives on community contributions. The project welcomes everyone and there are only a few requirements to make meaningful contributions. Requirements and conventions are documented in the README.md and CONTRIBUTING.md files.

Here are some of the most frequent tasks when working on Foreman documentation.

I want to start working on Foreman documentation
  1. Clone the repository from github.com:

    $ git clone git@github.com:theforeman/foreman-documentation.git
    $ cd foreman-documentation/
  2. Rename the remote:

    $ git remote rename origin upstream
  3. Optional: Ensure that your local master branch is tracking the master branch from the foreman-documentation repository from the theforeman organization:

    $ git status

    This automatically starts you on the latest commit of the default branch, which in this case is master.

  4. If you do not have a fork of the repository in your own account or organization already, create one.

    Go to github.com/theforeman/foreman-documentation and click Fork.

  5. Add your fork to your repository.

    $ git remote add github git@github.com:My_Name/foreman-documentation.git

    Your local repository now has two remotes: upstream and github.

I want to extend the Foreman documentation

For simple changes such as fixing a spelling mistake, you can create a pull request (PR) directly.

  1. Create a branch named, for example, fix_spelling. The git switch command changes the currently checked out branch, and -c creates the branch:

    $ git switch -c fix_spelling
  2. Make your change.

  3. Add your change and commit:

    $ git add guides/common/modules/abc.adoc
    $ git commit -m "Fix spelling of existing"

    I cannot emphasise the importance of good Git commit messages enough. A commit message tells the project maintainers what you have done, and because it's preserved along with the rest of the codebase, it serves as a historical footnote when someone's looking back through code to determine what's happened over its lifespan.

  4. Optional but recommended: View and verify the diff to the default branch. The default branch for foreman-documentation is called master, but other projects may name theirs differently (for example, main, dev, or devel.)

    $ git diff master
  5. Push your branch to Github. This publishes your change to your copy of the codebase.

    $ git push --set-upstream github fix_spelling
  6. Click on the link provided by Git in your terminal to create a pull request (PR).

    remote: Create a pull request for 'fix_spelling' on Github by visiting:
    remote:      https://github.com/_My_User_Account_/foreman-documentation/pull/new/fix_spelling
  7. Add an explanation on why the community should accept your change. This isn't necessary for a trivial PR, such as fixing a spelling mistake, but for major changes it's important.

More on Git What is Git? Git cheat sheet Markdown cheat sheet New Git articles I want to rebase my branch to master.
  1. Ensure your local master branch tracks the master branch from github.com/theforeman/foreman-documentation, not foreman-documentation in your own namespace:

    $ git switch master

    This should read Your branch is up to date with 'upstream/master', with upstream being the name of your remote repository pointing to github.com/theforeman/foreman-documentation. You can review your remotes by running git remote -v.

  2. Fetch possible changes from your remote. The git fetch command downloads the tracked branch from your remote, and the --all option updates all branches simultaneously. This is necessary when working with additional branches. The --prune option removes references to branches that no longer exist.

    $ git fetch --all --prune
  3. Pull possible changes from upstream/master into your local master branch. The git pull command copies commits from the branch you're tracking into your current branch. This is used to "update" your local master branch to the latest state of the master branch in your remote (Github, in this case.)

    $ git pull
  4. Rebase your branch to "master".

    $ git switch my_branch
    $ git rebase -i master
I have accidentally committed to master
  1. Create a branch to save your work:

    $ git switch -c my_feature
  2. Switch back to the master branch:

    $ git switch master
  3. Drop the last commit on master:

    $ git reset --soft HEAD~1
  4. Switch back to my_feature branch and continue working:

    $ git switch my_feature
I want to reword my commit message
  1. If you only have one commit on your branch, use git amend to change your last commit:

    $ git commit --amend

    This assumes that you don't have any other files added to your staging area (that is, you did not run git add My_File without also committing it.)

  2. Push your "change" to Github, using the --force option because the Git commit message is part of your existing commit, so you're changing the history on your branch.

    $ git push --force
I want to restructure multiple changes on a single branch
  1. Optional but strongly recommended: Fetch changes from Github.

    $ git switch master
    $ git fetch
    $ git pull

    This ensures that you directly incorporate any other changes into your branch in the order they've been merged to master.

  2. To restructure your work, rebase your branch and make changes as necessary. Rebasing to master means changing the parent commit of your first commit on your branch:

    $ git rebase --interactive master

    Replace the first word pick to modify the commit.

    • Use e to make actual changes to your commit. This interrupts your rebase!

    • Use f to combine a commit with its parent.

    • Use d to completely remove the commit from your branch.

    • Move the lines to change the order of your changes.

      After successfully rebasing, your own commits are on top of the last commit from master.

I want to copy a commit from another branch
  1. Get the commit ID from a stable branch (for example, a branch named 3.3), using the -n option to limit the number of commits.

    $ git log -n 5 3.3
  2. Replicate changes by cherry-picking commits to your branch. The -x option adds the commit ID to your commit message. This is only recommended when cherry-picking commits from a stable branch.

    $ git switch My_Branch
    $ git cherry-pick -x Commit_ID
More tips

At ATIX, we run a GitLab instance to share code, collaborate, and automate tests and builds internally. With the open source community surrounding the Foreman ecosystem, we rely on Github.

I recommend that you always point the remote named origin in any Git repository to your internal version control system. This prevents leaking information to external services when doing a git push based on pure muscle memory.

Additionally, I recommend using a fixed naming scheme for remotes. I always name the remote pointing to my own GitLab instance origin, the open source project upstream, and my fork on Github github.

For foreman-documentation, the repository has a relatively flat history. When working with a more complex structure, I tend to think of Git repositories in a very visual way with nodes (commits) pointing to nodes on lines (branches) that potentially intertwine. Graphical tools such as gitk or Git Cola can help visualize your Git history. Once you have fully grasped how Git works, you can move on to aliases, if you prefer the command line.

Before a big rebase with a lot of expected merge conflicts, I recommend creating a "backup" branch that you can quickly view diffs against. Note that it's pretty hard to irreversibly delete commits, so play around in your local Git repository before making big changes.

Git for tech writers

Git is a tremendous help for technical writers. Not only can you use Git to version your own content, but you can actively collaborate with others.

Follow along with this demo of how I use Git to write documentation for Foreman.

Image by:

Jonas Leupe on Unsplash

Git Documentation What to read next How writers can get work done better with Git This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License. Register or Login to post a comment.

Linux 6.1-rc6 Released - Still Coming In Larger Than Torvalds Would Like

Phoronix - Mon, 11/21/2022 - 08:28
Last week with Linux 6.1-rc5 there was concerns raised by Linus Torvalds that the v6.1 cycle may need an extra week of testing and fixes. Now Linux 6.1-rc6 is available with Torvalds' latest prognosis for the Linux 6.1 kernel cycle...

OpenRazer 3.5 Brings Support For Newer Razer Devices On Linux

Phoronix - Sun, 11/20/2022 - 22:24
While Razer still sadly isn't officially supporting their various gaming-focused computer peripherals under Linux, the OpenRazer project providing open-source drivers for Razer products continues working out well and offering broad hardware support under Linux...

Intel's IWD 2.0 Released For Modern Linux Wireless Daemon

Phoronix - Sun, 11/20/2022 - 20:00
One of countless great open-source projects from Intel over the years is IWD as a modern wireless daemon for WiFi devices on Linux. IWD has been in the works for over a half-decade as a new replacement to wpa_supplicant and with time has implemented many features and seen widespread adoption. Released this week was IWD 2.0 as the latest milestone for this open-source wireless daemon...

New Patches Allow More Easily Managing The AMD P-State Linux Driver

Phoronix - Sun, 11/20/2022 - 19:30
Since the introduction of the AMD P-State driver to the mainline kernel, enthusiasts and gamers have been experimenting with the amd_pstate driver and some distributions like Ubuntu have went with using this driver in place of ACPI CPUFreq by default for Zen 2 and newer processors. Patches posted this week by AMD make it easier to switch between the AMD P-State driver and ACPI CPUFreq...

Fixed Intel IFS Driver Ready To Go With Linux 6.2

Phoronix - Sun, 11/20/2022 - 19:11
In addition to Linux 6.2 promoting [DG2] Arc Graphics to stable, this next kernel version will no longer deem the Intel In-Field Scan (IFS) driver as "broken" now that it's API/ABI is in good shape...

Compute Accelerator Subsystem Hopes To Be Ready For Linux 6.2

Phoronix - Sun, 11/20/2022 - 18:25
Thanks to this year's Linux Plumbers Conference it looks like the compute accelerator subsystem/framework is finally coming together. The fourth and potentially final iteration of the accelerator framework patches have been sent out with hopes of them being mainlined for the upcoming Linux 6.2 kernel...

Libinput 1.22 Brings More Input Hardware Quirks, New Flat Acceleration Profile

Phoronix - Sun, 11/20/2022 - 18:18
Libinput 1.22 was released this weekend by José Expósito as the newest version of this widely-used input handling library that is now common to the Linux desktop by both X.Org and Wayland based environments...

Pages