linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Knowledge base
  • Cheat sheet
  • Capstone
  • Interview prep
home/terraform/how/tf-state-mv-rm-import

how/state

state mv, state rm, import: imperative operations on state

Three commands that edit the state file directly: rename an entry, forget a resource, pull an existing one in from the cloud. What they change, what they leave alone, and where they bite.

terraform.tfstate is Terraform's cache, and usually you don't have to touch it by hand. Apply writes everything in for you, refresh updates everything for you.

But there are cases where state and HCL diverge by address rather than by value:

  • you renamed a resource in HCL. To Terraform that reads as "destroy the old one, create a new one," and the cloud rebuilds for nothing.
  • you are pulling a module out of management. The physical resources have to survive that, you must not touch them.
  • someone created a bucket by hand in the AWS Console a year ago, and now you need to bring it under Terraform, but without destroy-and-recreate.

For each case there is a command: state mv, state rm, import. All three are imperative: they change state in place, the HCL stays on you. Hit ▶ and watch what each one does to the HCL/state/cloud triangle.

step 1/5·00 · starting position
$# три источника в инварианте# после успешного apply: HCL = state = cloudMAIN.TFHCLTERRAFORM.TFSTATEstateAWScloudaws_s3_bucket.oldaws_s3_bucket.oldid: linuxlab-3f4alinuxlab-3f4aбазовая позиция: один бакет, три согласованных источника

§ steps

  1. One S3 bucket is described in HCL as aws_s3_bucket.old, state has an entry with id linuxlab-3f4a, and in AWS there is a bucket with exactly that id. All three sources agree.

    From this point we split three ways: rename, remove, import.

recap

What matters about these three operations:

  • All three change state, not the cloud. They do not touch the physical AWS resources at all.
  • All three are imperative. You run them by hand, against a specific address, and the result is not reproducible from HCL. That means it does not repeat in CI and is not visible in git history.
  • That makes them an emergency tool. In a normal workflow you do not reach for them.

When you can and should use them:

  • state mv: rename a resource or move it into another module without recreating it. The most common case.
  • state rm: hand a resource over to another team or an outside system. The bucket keeps living, Terraform just stops tracking it. Often paired with terraform import on the new owner's side.
  • terraform import: bring a long-existing resource under management. The alternative is to recreate it from scratch, which for prod data is rarely possible.

Gotchas:

  • state rm does not warn about dependencies. If you removed a resource from state that others depend on, after plan they all start crying "this needs to be created again."
  • terraform import brings only the id into state. The attributes (tags, policies, encryption) you have to write into HCL by hand, then plan should show No changes. If it shows anything else, the state does not match what you described.

Terraform 1.5+ added declarative equivalents: the moved, removed, and import blocks. They are reproducible and live in git. That is the topic of the next explainer: tf-moved-removed-import-blocks.

§ dig into the knowledge base

  • tf-stateWhat state is and why it is the source of truth
  • tf-state-anatomyAnatomy of the state file
  • tf-importterraform import: bringing in an existing resource
  • tf-state-manipulationterraform state mv/rm/list: the full picture
  • tf-moved-blockThe declarative moved block

§ try it hands-on

  • ›tf-intermediate-07-state-manipulation- Operations on state: mv, rm, list
  • ›tf-intermediate-08-import- Import: bringing in an existing bucket
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies