#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5, M = 30;
const pair<int, int> INVALID = {-1, -1};
int n, m, q, sz[N], p[N], f[N], ans[N], basis[M];
map<pair<int, int>, int> mp, w;
pair<int, int> Q[N];
struct Edge {
  int l, r, x, y, d;
};
struct Logger {
  int x, y, sx, sy, cyc;
};
vector<Edge> st[4 * N];
void add(int i, int L, int R, Edge& e) {
  if (L > e.r || R < e.l) return;
  if (L >= e.l && R <= e.r) {
    st[i].push_back(e);
  } else {
    int mid = (L + R) >> 1;
    add(i << 1, L, mid, e);
    add(i << 1 | 1, mid + 1, R, e);
  }
}
int root(int x) {
  for (; x != p[x]; x = p[x])
    ;
  return x;
}
int path_val(int x) {
  int res = 0;
  for (; x != p[x]; x = p[x]) res ^= f[x];
  return res;
}
int purify(int x) {
  for (int i = M - 1; i >= 0; i--) {
    if (x & (1 << i)) x ^= basis[i];
  }
  return x;
}
void merge(int x, int y, int d, stack<Logger>& log) {
  int rx = root(x), ry = root(y);
  Logger top = {rx, ry, sz[rx], sz[ry], 0};
  if (rx == ry) {
    top.cyc = purify(path_val(x) ^ path_val(y) ^ d);
    for (int i = M - 1; i >= 0; i--) {
      if (top.cyc & (1 << i)) {
        basis[i] = top.cyc;
        break;
      }
    }
  } else {
    if (sz[rx] > sz[ry]) {
      sz[rx] += sz[ry];
      p[ry] = rx;
      f[ry] = path_val(y) ^ path_val(x) ^ d;
    } else {
      sz[ry] += sz[rx];
      p[rx] = ry;
      f[rx] = path_val(x) ^ path_val(y) ^ d;
    }
  }
  log.push(top);
}
void roll_back(stack<Logger>& log) {
  for (; !log.empty(); log.pop()) {
    Logger top = log.top();
    p[top.x] = top.x;
    sz[top.x] = top.sx;
    f[top.x] = 0;
    p[top.y] = top.y;
    sz[top.y] = top.sy;
    f[top.y] = 0;
    if (top.cyc) {
      for (int i = M - 1; i >= 0; i--)
        if (top.cyc & (1 << i)) {
          basis[i] = 0;
          break;
        }
    }
  }
}
void dfs(int i, int L, int R) {
  stack<Logger> log;
  for (Edge e : st[i]) {
    merge(e.x, e.y, e.d, log);
  }
  if (L == R) {
    if (Q[L] != INVALID) {
      int x = Q[L].first, y = Q[L].second;
      ans[L] = purify(path_val(x) ^ path_val(y));
    }
  } else {
    dfs(i << 1, L, (L + R) / 2);
    dfs(i << 1 | 1, (L + R) / 2 + 1, R);
  }
  roll_back(log);
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) p[i] = i, sz[i] = 1;
  for (int i = 1; i <= m; i++) {
    int x, y, d;
    cin >> x >> y >> d;
    w[{x, y}] = d;
    mp[{x, y}] = 0;
  }
  cin >> q;
  for (int i = 1; i <= q; i++) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y, d;
      cin >> x >> y >> d;
      mp[{x, y}] = i;
      w[{x, y}] = d;
    }
    if (t == 2) {
      int x, y;
      cin >> x >> y;
      Edge e = {mp[{x, y}], i - 1, x, y, w[{x, y}]};
      add(1, 0, q, e);
      mp[{x, y}] = w[{x, y}] = -1;
    }
    if (t == 3) {
      int x, y;
      cin >> x >> y;
      Q[i] = {x, y};
    } else
      Q[i] = INVALID;
  }
  for (auto it = mp.begin(); it != mp.end(); it++) {
    int x = (it->first).first, y = (it->first).second, l = it->second,
        d = w[{x, y}];
    if (l == -1) continue;
    Edge e = {l, q, x, y, d};
    add(1, 0, q, e);
  }
  dfs(1, 0, q);
  for (int i = 1; i <= q; i++) {
    if (Q[i] != INVALID) {
      cout << ans[i] << "\n";
    }
  }
}
