4

Using rugged how do you perform the following operations: fetch, pull and rebase?

I am using the development branch and after reviewing its documentation found here as a guide to the Remote class.

EDIT: Since git pull is just a shorthand for git fetch and git merge FETCH_HEAD the better question is how to perform git fetch, git merge and git rebase.

rhodee
  • 1,257
  • 1
  • 14
  • 27

2 Answers2

11

git fetch:

remote = Rugged::Remote.lookup(repo, "origin")
remote.connect(:fetch) do |r|
  r.download
  r.update_tips!
end

git merge:

merge_index = repo.merge_commits(
  Rugged::Branches.lookup(repo, "master").tip,
  Rugged::Branches.lookup(repo, "origin/master").tip
)

raise "Conflict detected!" if merge_index.conflicts?

merge_commit = Rugged::Commit.create(repo, {
  parents: [
    Rugged::Branches.lookup(repo, "master").tip,
    Rugged::Branches.lookup(repo, "origin/master").tip
  ],
  tree: merge_index.write_tree(repo),
  message: 'Merged `origin/master` into `master`',
  author:    { name: "User", email: "example@test.com" },
  committer: { name: "User", email: "example@test.com" },
  update_ref: 'master'
})

git rebase:

Rebasing was not implemented yet in libgit2, and thus is not available in Rugged.


In general, your use case sounds very high level, while the rugged API is currently a bit more focused on low-level git repository access and modification. Eventually, we'll also have many higher-level helpers (like a more simple/correct pull) in the future, but we're not there yet.

4

The answer above seems to be outdated. The syntax has changed. I need to implement a pull action which i am trying to do by a fetch and then a merge and commit. For fetching i use the fetch method like this

repo.fetch('origin', [repo.head.name], credentials: credits)

And it seems to actually get something since the returned hash is full with information about what has been fetched. However, it is not written to disk. I would expect the branch to be behind several commits when i do git status in the command line but it is not. If i fetch a second time with the same command above then nothing is fetched. This is probably because it has already been fetched the first time but then i dont see where the fetch is.

Now if i go ahead and do the fetch manually in the command line and then try to merge the local copy of the remote branch and the local branch (local changes are already committed) using the following code

ref_name = repo.head.name                            # refs/heads/branchname
branch_name = ref_name.sub(/^refs\/heads\//, '')     # branchname
remote_name = "#{remote}/#{branch_name}"             # origin/branchname
remote_ref = "refs/heads/#{remote_name}"             # refs/heads/origin/branchname

local_branch = repository.branches[branch_name]
remote_branch = repository.branches[remote_name]

index = repo.merge_commits(local_branch.target, remote_branch.target)

options = {
  author:     { time: Time.now }.merge(author),
  committer:  { time: Time.now }.merge(committer),
  message:    'merged',
  parents:    [
    local_branch.target,
    remote_branch.target
  ],
  tree:       index.write_tree(repository),
  update_ref: 'HEAD'
}
Rugged::Commit.create repo, options

It creates the commit as expected. The commit is also written to disk and is visible in the fistory. But for some reason the branch has now uncommitted changes. The local file contents have not changed. I would expect them to have the contents of the fetched commit.

Can anyone please provide a working example for a fetch, merge, commit? The version of rugged at time of writing this is 0.22.0b3

Update 1

This will bring my working tree to the wanted state

repo.checkout ref_name, strategy: :force

Update2

I found out how to fetch and save the state to disk

r = repo.remotes[remote]
r.fetch(credentials: git_credentials)
r.save
Ginie
  • 41
  • 3