tests/testthat/test-commit.R

test_that("creating signatures", {
  now <- Sys.time()
  name <- 'Testing Jerry'
  email <- 'test@jerry.com'
  author <- sprintf("%s <%s>", name, email)

  sig <- git_signature(name, email)
  sigdata <- git_signature_parse(sig)
  expect_equal(sigdata$name, name)
  expect_equal(sigdata$email, email)
  expect_lt(difftime(sigdata$time, now, 'secs'), 1)

  yesterday <- now - 24 * 60 * 60
  sig <- git_signature(name, email, time = yesterday)
  sigdata <- git_signature_parse(sig)
  expect_equal(sigdata$name, name)
  expect_lt(difftime(sigdata$time, yesterday, 'secs'), 1)
})

test_that("adding and removing files", {
  repo <- git_init(tempfile("gert-tests-commit"))
  on.exit(unlink(repo, recursive = TRUE))

  expect_equal(nrow(git_ls(repo = repo)), 0)
  write.csv(iris, file.path(repo, 'iris.csv'))
  write.csv(cars, file.path(repo, 'cars.csv'))
  git_add(c('cars.csv', 'iris.csv'), repo = repo)
  expect_equal(nrow(git_ls(repo = repo)), 2)
  expect_equal(git_ls(repo = repo)$path, c('cars.csv', 'iris.csv'))
  git_rm(c('cars.csv', 'iris.csv'), repo = repo)
  expect_equal(nrow(git_ls(repo = repo)), 0)
  remotes <- git_remote_list(repo)
  expect_equal(nrow(remotes), 0)
})

test_that("creating a commit", {
  repo <- git_init(tempfile("gert-tests-commit"))
  on.exit(unlink(repo, recursive = TRUE))
  configure_local_user(repo)

  expect_equal(nrow(git_ls(repo = repo)), 0)
  dir.create(file.path(repo, 'src'))
  write.csv(cars, file.path(repo, 'src', 'cars.csv'))
  git_add('src/cars.csv', repo = repo)
  git_commit("Added cars.csv file", repo = repo)
  stats <- git_stat_files('src/cars.csv', repo = repo)
  expect_equal(stats$file, 'src/cars.csv')
  expect_equal(stats$commits, 1)
  expect_equal(stats$created, stats$modified)

  # Another commit before that
  write.csv(iris, file.path(repo, 'iris.csv'))
  git_add("iris.csv", repo = repo)
  timestamp <- round(Sys.time() - 48 * 60 * 60)
  sig2 <- git_signature('nobody', 'nobody@gmail.com', time = timestamp)
  git_commit("Added iris.csv also", author = sig2, repo = repo)

  # Inspect the log file
  log <- git_log(repo = repo)
  expect_equal(log$author[2], local_author(repo))
  expect_equal(
    format(log$time[1], format = "%Y-%m-%d %H:%M:%S %Z"),
    format(timestamp, format = "%Y-%m-%d %H:%M:%S %Z")
  )
})

test_that("Passing ref into git_ls gives correct info", {
  t <- tempfile()
  dir.create(t)
  writeLines(c("# Example", "", "example repo"), file.path(t, "README.md"))
  git_init(t)
  git_add(".", repo = t)
  user <- "author <author@example.com>"
  sha <- git_commit("initial", author = user, committer = user, repo = t)
  without_ref <- git_ls(repo = t)
  with_ref <- git_ls(repo = t, ref = "HEAD")
  expect_equal(with_ref, without_ref)
})

test_that("creating a commit in another directory without author works", {
  path <- tempfile("gert-tests-commit")
  on.exit(unlink(path, recursive = TRUE))

  dir.create(path)
  repo <- git_init(path)
  configure_local_user(repo)
  writeLines("content", file.path(path, "file"))
  git_add("file", repo = path)
  git_commit("Added file", repo = repo)

  log <- git_log(repo = repo)
  expect_equal(log$author, local_author(repo))
})

test_that("status reports a conflicted file", {
  repo <- git_init(tempfile("gert-test-conflicts"))
  on.exit(unlink(repo, recursive = TRUE))
  configure_local_user(repo)

  foo_path <- file.path(repo, "foo.txt")
  bar_path <- file.path(repo, "bar.txt")

  writeLines("cranky-crab-legs", foo_path)
  git_add("foo.txt", repo = repo)
  base <- git_commit("Add a file", repo = repo)
  main <- git_branch(repo = repo)

  git_branch_create("my-branch", repo = repo)
  writeLines("cranky-CRAB-LEGS", foo_path)
  git_add("foo.txt", repo = repo)
  git_commit("Uppercase last 2 words", repo = repo)

  git_branch_checkout(main, repo = repo)
  expect_equal(git_merge_analysis("my-branch", repo = repo), "fastforward")

  writeLines("CRANKY-CRAB-legs", foo_path)
  git_add("foo.txt", repo = repo)
  git_commit("Uppercase first 2 words", repo = repo)

  writeLines(c("CRANKY-CRAB-legs", "One more line"), foo_path)
  git_add("foo.txt", repo = repo)
  git_commit("Add another commit", repo = repo)

  writeLines("Nothing special", bar_path)
  git_add("bar.txt", repo = repo)
  git_commit("Non-conflicting commit", repo = repo)

  expect_equal(base, git_merge_find_base("my-branch", repo = repo))
  expect_equal(git_merge_analysis(base, repo = repo), "up_to_date")
  expect_equal(git_merge_analysis('my-branch', repo = repo), "normal")

  # What if we would rebase
  rebase_info <- git_rebase_list("my-branch", repo = repo)
  expect_equal(rebase_info$type, rep("pick", 3))
  expect_equal(rebase_info$commit, rev(head(git_log(repo = repo), -1)$commit))
  expect_equal(rebase_info$conflicts, c(T, T, F))
  expect_error(
    git_rebase_commit("my-branch", repo = repo),
    class = "GIT_EMERGECONFLICT"
  )
  expect_error(git_branch_fast_forward("my-branch", repo = repo))

  # Merge returns FALSE due to conflicts
  git_merge("my-branch", repo = repo)
  status <- git_status(repo = repo)
  expect_equal(status$file, "foo.txt")
  expect_equal(status$status, "conflicted")
  expect_equal(git_conflicts(repo = repo)$our, "foo.txt")
  expect_false(status$staged)

  # Abort and cleanup
  git_merge_abort(repo = repo)
  expect_equal(nrow(git_status(repo = repo)), 0)
  expect_equal(nrow(git_conflicts(repo = repo)), 0)

  # Merge again :)
  git_merge("my-branch", repo = repo)
  status <- git_status(repo = repo)
  expect_equal(status$file, "foo.txt")
  expect_equal(status$status, "conflicted")
  expect_equal(git_conflicts(repo = repo)$our, "foo.txt")
  expect_false(status$staged)

  # Resolve the conflict
  conflicts <- git_conflicts(repo = repo)
  expect_equal(conflicts$our, status$file)
  writeLines("Conflict is resolved", foo_path)
  git_add('foo.txt', repo = repo)
  git_commit("Resolve merge conflict", repo = repo)
  expect_length(git_conflicts(repo = repo)$our, 0)
  expect_length(git_status(repo = repo)$file, 0)
})

test_that("git_log path filtering works", {
  repo <- git_init(tempfile("gert-tests-commit"))
  on.exit(unlink(repo, recursive = TRUE))
  configure_local_user(repo)

  writeLines("hello", file.path(repo, "foo.txt"))
  git_add("foo.txt", repo = repo)
  git_commit("Add foo.txt", repo = repo)

  writeLines("world", file.path(repo, "bar.txt"))
  git_add("bar.txt", repo = repo)
  git_commit("Add bar.txt", repo = repo)

  writeLines("updated", file.path(repo, "foo.txt"))
  git_add("foo.txt", repo = repo)
  git_commit("Update foo.txt", repo = repo)

  log_all <- git_log(repo = repo)
  expect_equal(nrow(log_all), 3)

  log_foo <- git_log(path = "foo.txt", repo = repo)
  expect_equal(nrow(log_foo), 2)
  expect_true(all(grepl("foo", log_foo$message)))

  log_bar <- git_log(path = "bar.txt", repo = repo)
  expect_equal(nrow(log_bar), 1)
  expect_match(log_bar$message, "bar.txt")
})

test_that("reverting a commit", {
  repo <- git_init(tempfile("gert-tests-revert"))
  on.exit(unlink(repo, recursive = TRUE))
  configure_local_user(repo)

  writeLines("hello", file.path(repo, "hello.txt"))
  git_add("hello.txt", repo = repo)
  git_commit("First commit", repo = repo)

  writeLines("world", file.path(repo, "hello.txt"))
  git_add("hello.txt", repo = repo)
  second <- git_commit("Second commit", repo = repo)

  # Default: stages + commits
  revert_sha <- git_revert(second, repo = repo)
  expect_type(revert_sha, "character")
  log <- git_log(repo = repo)
  expect_shape(log, nrow = 3)
  expect_match(log$message[1], '^Revert "Second commit"')
  expect_equal(readLines(file.path(repo, "hello.txt")), "hello")

  # commit = FALSE: only stages
  writeLines("again", file.path(repo, "hello.txt"))
  git_add("hello.txt", repo = repo)
  third <- git_commit("Third commit", repo = repo)
  result <- git_revert(third, commit = FALSE, repo = repo)
  expect_null(result)
  status <- git_status(repo = repo)
  expect_true(any(status$staged))
})

test_that("git_revert accepts ancestor references like HEAD~1", {
  repo <- git_init(tempfile("gert-tests-revert-ancestor"))
  on.exit(unlink(repo, recursive = TRUE))
  configure_local_user(repo)

  writeLines("a", file.path(repo, "a.txt"))
  git_add("a.txt", repo = repo)
  git_commit("First commit", repo = repo)

  # Second commit touches its own file so reverting it won't conflict with Third
  writeLines("b", file.path(repo, "b.txt"))
  git_add("b.txt", repo = repo)
  git_commit("Second commit", repo = repo)

  writeLines("c", file.path(repo, "c.txt"))
  git_add("c.txt", repo = repo)
  git_commit("Third commit", repo = repo)

  # HEAD~1 resolves to "Second commit"
  revert_sha <- git_revert("HEAD~1", repo = repo)
  expect_type(revert_sha, "character")
  log <- git_log(repo = repo)
  expect_match(log$message[1], '^Revert "Second commit"')
})

test_that("git_revert raises an error for an invalid commit", {
  repo <- git_init(tempfile("gert-tests-revert-invalid"))
  on.exit(unlink(repo, recursive = TRUE))
  configure_local_user(repo)

  writeLines("hello", file.path(repo, "hello.txt"))
  git_add("hello.txt", repo = repo)
  git_commit("First commit", repo = repo)

  expect_error(git_revert("notacommit", repo = repo), "notacommit")
})

Try the gert package in your browser

Any scripts or data that you put into this service are public.

gert documentation built on July 22, 2026, 5:07 p.m.